Browse Source

推送代码

qmj 4 months ago
commit
63ef324e23
100 changed files with 15827 additions and 0 deletions
  1. 219 0
      .gitignore
  2. BIN
      .idea/.cache/.Apifox_Helper/.toolWindow.db
  3. 10 0
      .idea/.gitignore
  4. 10 0
      .idea/ApifoxUploaderProjectSetting.xml
  5. 7 0
      .idea/MarsCodeWorkspaceAppSettings.xml
  6. 7 0
      .idea/ProjectStorage.xml
  7. 8 0
      .idea/inspectionProfiles/Project_Default.xml
  8. 13 0
      .idea/modules.xml
  9. 124 0
      .idea/uiDesigner.xml
  10. 12 0
      bin/clean.bat
  11. 12 0
      bin/package.bat
  12. 14 0
      bin/run.bat
  13. 226 0
      pom.xml
  14. 126 0
      ruoyi-admin/pom.xml
  15. 8 0
      ruoyi-admin/ruoyi-admin.iml
  16. 27 0
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
  17. 18 0
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
  18. 154 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/OperatingHoursController.java
  19. 190 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosCollectController.java
  20. 157 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosFenleiController.java
  21. 442 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosFoodController.java
  22. 402 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java
  23. 117 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosTypeController.java
  24. 116 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ServiceTypeController.java
  25. 110 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShPosReviewController.java
  26. 204 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShQuanyiController.java
  27. 214 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShSalesPromotionController.java
  28. 218 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShindexController.java
  29. 14 0
      ruoyi-admin/src/main/java/com/ruoyi/app/mendian/dto/ExportInput.java
  30. 105 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/DistanceMultiplierController.java
  31. 172 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/InfoAddressController.java
  32. 45 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PointController.java
  33. 48 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PointController.java~
  34. 105 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosFreightController.java
  35. 1684 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java
  36. 212 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderRatingController.java
  37. 231 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosReviewController.java
  38. 304 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/TaxiOrderController.java
  39. 140 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/TaxiPricesController.java
  40. 128 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/TestTask.java
  41. 55 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/ZaloPayCommonService.java
  42. 60 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/OrderPositionInfo.java
  43. 77 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/OrderPushBodyDto.java
  44. 20 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/PositionDto.java
  45. 21 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/QsDto.java
  46. 142 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/BankCardController.java
  47. 27 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/DisbursementController.java
  48. 105 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/IpnLogController.java
  49. 446 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/PayController.java
  50. 401 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java
  51. 401 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java~
  52. 475 0
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/ZaloPayController.java
  53. 225 0
      ruoyi-admin/src/main/java/com/ruoyi/app/promotion/SalesPromotionController.java
  54. 128 0
      ruoyi-admin/src/main/java/com/ruoyi/app/promotion/SocialFeedbackController.java
  55. 105 0
      ruoyi-admin/src/main/java/com/ruoyi/app/qiyefuwu/SysQiyejieshaoController.java
  56. 87 0
      ruoyi-admin/src/main/java/com/ruoyi/app/report/StatisticsController.java
  57. 101 0
      ruoyi-admin/src/main/java/com/ruoyi/app/service/WalletService.java
  58. 40 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/AdsController.java
  59. 790 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/InfoUserController.java
  60. 151 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/PosMarginController.java
  61. 165 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/RiderPositionController.java
  62. 175 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/SysFeedbackController.java
  63. 123 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/SysHelpController.java
  64. 106 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/UserAppIndexController.java
  65. 117 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/UserFootprintController.java
  66. 105 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/UserMarginController.java
  67. 70 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/UserPointController.java
  68. 328 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/VideoCallController.java
  69. 380 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/VipUserQuanyiController.java
  70. 44 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/CouponDto.java
  71. 12 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/PointOutput.java
  72. 15 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/ReceiveQuanyiInput.java
  73. 15 0
      ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/StoreOutput.java
  74. 113 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/AppVersionController.java
  75. 140 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/DateUtil.java
  76. 140 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/DateUtil.java~
  77. 58 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/GetJvli.java
  78. 53 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/GetVipqy.java
  79. 66 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/HmacUtil.java
  80. 231 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/HttpKit.java
  81. 598 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/ImageCompressUtils.java
  82. 195 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/IpUtils.java
  83. 271 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/Md5Pay.java
  84. 169 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/PayMD5.java
  85. 35 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/PayPush.java
  86. 161 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/RSAUtil.java
  87. 144 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/RSAUtils.java
  88. 145 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/RsaMima.java
  89. 138 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/SftSignUtil.java
  90. 159 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/StrKit.java
  91. 241 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/SysFileInfoController.java
  92. 85 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/UUIDUtil.java
  93. 132 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/VNPay.java
  94. 24 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/event/PushEvent.java
  95. 29 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/event/PushEventListener.java
  96. 28 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/event/PushEventService.java
  97. 24 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/trtc/Base64URL.java
  98. 318 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/trtc/TLSSigAPIv2.java
  99. 250 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/zaloPay/ZaloPay.java
  100. 15 0
      ruoyi-admin/src/main/java/com/ruoyi/app/utils/zaloPay/ZaloPayApiProperties.java

+ 219 - 0
.gitignore

@@ -0,0 +1,219 @@
+
+.idea/vcs.xml
+.idea/misc.xml
+.idea/jpa-buddy.xml
+.idea/jarRepositories.xml
+.idea/encodings.xml
+.idea/compiler.xml
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosOrder.class
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosOrder.class
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosOrder.class
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosOrder.class
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosOrder.class
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+*.class
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosOrder.class
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosAppeal.class
+ruoyi-system/target/classes/mapper/system/PosAppealMapper.xml
+ruoyi-system/target/classes/mapper/system/PosFeedbackMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosAppeal.class
+ruoyi-system/target/classes/mapper/system/PosAppealMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosAppeal.class
+ruoyi-system/target/classes/mapper/system/PosAppealMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/application.yml
+ruoyi-admin/target/classes/com/ruoyi/app/mendian/PosCollectController.class
+ruoyi-admin/target/classes/com/ruoyi/app/mendian/PosFenleiController.class
+ruoyi-admin/target/classes/com/ruoyi/app/mendian/PosFoodController.class
+ruoyi-admin/target/classes/com/ruoyi/app/mendian/PosStoreController.class
+ruoyi-admin/target/classes/com/ruoyi/app/mendian/PosTypeController.class
+ruoyi-admin/target/classes/com/ruoyi/app/order/PosOrderController.class
+ruoyi-admin/target/classes/com/ruoyi/app/order/TestTask.class
+ruoyi-admin/target/classes/com/ruoyi/app/pay/UserBillingController.class
+ruoyi-admin/target/classes/com/ruoyi/app/user/InfoUserController.class
+ruoyi-admin/target/classes/com/ruoyi/app/utils/SysFileInfoController.class
+ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CommonController.class
+ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysLoginController.class
+ruoyi-admin/target/classes/i18n/messages.properties
+ruoyi-admin/target/classes/i18n/messages_en_US.properties
+ruoyi-admin/target/classes/i18n/messages_vi.properties
+ruoyi-admin/target/classes/i18n/messages_zh_CN.properties
+ruoyi-admin/target/classes/i18n/messages_zh_TW.properties
+ruoyi-admin/target/maven-archiver/pom.properties
+ruoyi-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-admin/target/ruoyi-admin.jar
+ruoyi-admin/target/ruoyi-admin.jar.original
+ruoyi-common/target/classes/com/ruoyi/common/utils/file/FileUploadUtils.class
+ruoyi-common/target/maven-archiver/pom.properties
+ruoyi-common/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-common/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-common/target/ruoyi-common-3.8.5.jar
+ruoyi-framework/target/classes/com/ruoyi/framework/config/SecurityConfig.class
+ruoyi-framework/target/maven-archiver/pom.properties
+ruoyi-framework/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-framework/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-framework/target/ruoyi-framework-3.8.5.jar
+ruoyi-generator/target/maven-archiver/pom.properties
+ruoyi-generator/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-generator/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-generator/target/ruoyi-generator-3.8.5.jar
+ruoyi-quartz/target/maven-archiver/pom.properties
+ruoyi-quartz/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-quartz/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-quartz/target/ruoyi-quartz-3.8.5.jar
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosFenlei.class
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosFood.class
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosStore.class
+ruoyi-system/target/classes/com/ruoyi/system/domain/PosType.class
+ruoyi-system/target/classes/com/ruoyi/system/mapper/PosOrderMapper.class
+ruoyi-system/target/classes/com/ruoyi/system/mapper/PosStoreMapper.class
+ruoyi-system/target/classes/com/ruoyi/system/mapper/UserBillingMapper.class
+ruoyi-system/target/classes/com/ruoyi/system/service/impl/PosStoreServiceImpl.class
+ruoyi-system/target/classes/com/ruoyi/system/utils/GetArea.class
+ruoyi-system/target/classes/mapper/chanting/PosFoodMapper.xml
+ruoyi-system/target/classes/mapper/chanting/PosStoreMapper.xml
+ruoyi-system/target/classes/mapper/fenlei/PosTypeMapper.xml
+ruoyi-system/target/classes/mapper/system/PosFenleiMapper.xml
+ruoyi-system/target/classes/mapper/system/PosOrderMapper.xml
+ruoyi-system/target/maven-archiver/pom.properties
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+ruoyi-system/target/ruoyi-system-3.8.5.jar
+ruoyi-admin/target/classes/application.yml

BIN
.idea/.cache/.Apifox_Helper/.toolWindow.db


+ 10 - 0
.idea/.gitignore

@@ -0,0 +1,10 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Zeppelin ignored files
+/ZeppelinRemoteNotebooks/

File diff suppressed because it is too large
+ 10 - 0
.idea/ApifoxUploaderProjectSetting.xml


+ 7 - 0
.idea/MarsCodeWorkspaceAppSettings.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
+    <option name="ckgOperationStatus" value="SUCCESS" />
+    <option name="progress" value="1.0" />
+  </component>
+</project>

+ 7 - 0
.idea/ProjectStorage.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectStorage">
+    <option name="path" value="覃明健-&gt;CTE" />
+    <option name="projectId" value="4661c695547c000" />
+  </component>
+</project>

+ 8 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,8 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,org.apache.http.impl.client.HttpClients,createDefault" />
+    </inspection_tool>
+  </profile>
+</component>

+ 13 - 0
.idea/modules.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/ruoyi-admin/ruoyi-admin.iml" filepath="$PROJECT_DIR$/ruoyi-admin/ruoyi-admin.iml" />
+      <module fileurl="file://$PROJECT_DIR$/ruoyi-common/ruoyi-common.iml" filepath="$PROJECT_DIR$/ruoyi-common/ruoyi-common.iml" />
+      <module fileurl="file://$PROJECT_DIR$/ruoyi-framework/ruoyi-framework.iml" filepath="$PROJECT_DIR$/ruoyi-framework/ruoyi-framework.iml" />
+      <module fileurl="file://$PROJECT_DIR$/ruoyi-generator/ruoyi-generator.iml" filepath="$PROJECT_DIR$/ruoyi-generator/ruoyi-generator.iml" />
+      <module fileurl="file://$PROJECT_DIR$/ruoyi-quartz/ruoyi-quartz.iml" filepath="$PROJECT_DIR$/ruoyi-quartz/ruoyi-quartz.iml" />
+      <module fileurl="file://$PROJECT_DIR$/ruoyi-system/ruoyi-system.iml" filepath="$PROJECT_DIR$/ruoyi-system/ruoyi-system.iml" />
+    </modules>
+  </component>
+</project>

+ 124 - 0
.idea/uiDesigner.xml

@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>

+ 12 - 0
bin/clean.bat

@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 清理工程target生成路径。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+call mvn clean
+
+pause

+ 12 - 0
bin/package.bat

@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 打包Web工程,生成war/jar包文件。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+call mvn clean package -Dmaven.test.skip=true
+
+pause

+ 14 - 0
bin/run.bat

@@ -0,0 +1,14 @@
+@echo off
+echo.
+echo [信息] 使用Jar命令运行Web工程。
+echo.
+
+cd %~dp0
+cd ../ruoyi-admin/target
+
+set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
+
+java -jar %JAVA_OPTS% ruoyi-admin.jar
+
+cd bin
+pause

+ 226 - 0
pom.xml

@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	
+    <groupId>com.ruoyi</groupId>
+    <artifactId>ruoyi</artifactId>
+    <version>3.8.5</version>
+
+    <name>ruoyi</name>
+    <url>http://www.ruoyi.vip</url>
+    <description>若依管理系统</description>
+    
+    <properties>
+        <ruoyi.version>3.8.5</ruoyi.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+        <druid.version>1.2.16</druid.version>
+        <bitwalker.version>1.21</bitwalker.version>
+        <swagger.version>3.0.0</swagger.version>
+        <kaptcha.version>2.3.3</kaptcha.version>
+        <pagehelper.boot.version>1.4.6</pagehelper.boot.version>
+        <fastjson.version>2.0.25</fastjson.version>
+        <oshi.version>6.4.0</oshi.version>
+        <commons.io.version>2.11.0</commons.io.version>
+        <commons.collections.version>3.2.2</commons.collections.version>
+        <poi.version>4.1.2</poi.version>
+        <velocity.version>2.3</velocity.version>
+        <jwt.version>0.9.1</jwt.version>
+    </properties>
+	
+    <!-- 依赖声明 -->
+    <dependencyManagement>
+        <dependencies>
+
+            <!-- SpringBoot的依赖配置-->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>2.5.14</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- 阿里数据库连接池 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid-spring-boot-starter</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+
+            <!-- 解析客户端操作系统、浏览器等 -->
+            <dependency>
+                <groupId>eu.bitwalker</groupId>
+                <artifactId>UserAgentUtils</artifactId>
+                <version>${bitwalker.version}</version>
+            </dependency>
+
+            <!-- pagehelper 分页插件 -->
+            <dependency>
+                <groupId>com.github.pagehelper</groupId>
+                <artifactId>pagehelper-spring-boot-starter</artifactId>
+                <version>${pagehelper.boot.version}</version>
+            </dependency>
+
+            <!-- 获取系统信息 -->
+            <dependency>
+                <groupId>com.github.oshi</groupId>
+                <artifactId>oshi-core</artifactId>
+                <version>${oshi.version}</version>
+            </dependency>
+
+            <!-- Swagger3依赖 -->
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-boot-starter</artifactId>
+                <version>${swagger.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>io.swagger</groupId>
+                        <artifactId>swagger-models</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <!-- io常用工具类 -->
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>${commons.io.version}</version>
+            </dependency>
+
+            <!-- excel工具 -->
+            <dependency>
+                <groupId>org.apache.poi</groupId>
+                <artifactId>poi-ooxml</artifactId>
+                <version>${poi.version}</version>
+            </dependency>
+
+            <!-- velocity代码生成使用模板 -->
+            <dependency>
+                <groupId>org.apache.velocity</groupId>
+                <artifactId>velocity-engine-core</artifactId>
+                <version>${velocity.version}</version>
+            </dependency>
+
+            <!-- collections工具类 -->
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>${commons.collections.version}</version>
+            </dependency>
+
+            <!-- 阿里JSON解析器 -->
+            <dependency>
+                <groupId>com.alibaba.fastjson2</groupId>
+                <artifactId>fastjson2</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+
+            <!-- Token生成与解析-->
+            <dependency>
+                <groupId>io.jsonwebtoken</groupId>
+                <artifactId>jjwt</artifactId>
+                <version>${jwt.version}</version>
+            </dependency>
+
+            <!-- 验证码 -->
+            <dependency>
+                <groupId>pro.fessional</groupId>
+                <artifactId>kaptcha</artifactId>
+                <version>${kaptcha.version}</version>
+            </dependency>
+
+            <!-- 定时任务-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-quartz</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 代码生成-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-generator</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 核心模块-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-framework</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 系统模块-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-system</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 通用工具-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <modules>
+        <module>ruoyi-admin</module>
+        <module>ruoyi-framework</module>
+        <module>ruoyi-system</module>
+        <module>ruoyi-quartz</module>
+        <module>ruoyi-generator</module>
+        <module>ruoyi-common</module>
+    </modules>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>

+ 126 - 0
ruoyi-admin/pom.xml

@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>3.8.5</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>ruoyi-admin</artifactId>
+
+    <description>
+        web服务入口
+    </description>
+
+    <dependencies>
+
+        <!-- spring-boot-devtools -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional> <!-- 表示依赖不会传递 -->
+        </dependency>
+        <!-- trtc  tls-sig-api-v2 -->
+        <dependency>
+            <groupId>com.github.tencentyun</groupId>
+            <artifactId>tls-sig-api-v2</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <!-- swagger3-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.integration</groupId>
+            <artifactId>spring-integration-mqtt</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.19</version>
+        </dependency>
+
+        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+
+         <!-- Mysql驱动包 -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>8.0.22</version>
+        </dependency>
+
+        <!-- 核心模块-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-framework</artifactId>
+        </dependency>
+
+        <!-- 定时任务-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-quartz</artifactId>
+        </dependency>
+
+        <!-- 代码生成-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-generator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <version>RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.14</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>
+           </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>

+ 8 - 0
ruoyi-admin/ruoyi-admin.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4">
+  <component name="FacetManager">
+    <facet type="Spring" name="Spring">
+      <configuration />
+    </facet>
+  </component>
+</module>

+ 27 - 0
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java

@@ -0,0 +1,27 @@
+package com.ruoyi;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+/**
+ * 启动程序
+ *
+ * @author ruoyi
+ */
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+@MapperScan("com.ruoyi.*.mapper")
+@EnableAsync
+@EnableRetry
+public class RuoYiApplication
+{
+    public static void main(String[] args)
+    {
+        // System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(RuoYiApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  跑腿王启动成功   ლ(´ڡ`ლ)゙ ");
+    }
+}

+ 18 - 0
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java

@@ -0,0 +1,18 @@
+package com.ruoyi;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ * 
+ * @author ruoyi
+ */
+public class RuoYiServletInitializer extends SpringBootServletInitializer
+{
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+    {
+        return application.sources(RuoYiApplication.class);
+    }
+}

+ 154 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/OperatingHoursController.java

@@ -0,0 +1,154 @@
+package com.ruoyi.app.mendian;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.OperatingHours;
+import com.ruoyi.system.service.IOperatingHoursService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * OperatingHoursController
+ * 
+ * @author ruoyi
+ * @date 2025-02-11
+ */
+@RestController
+@RequestMapping("/hours")
+public class OperatingHoursController extends BaseController
+{
+    @Autowired
+    private IOperatingHoursService operatingHoursService;
+
+    /**
+     * 添加时间段
+     * @param operatingHours
+     * @return
+     */
+    @Anonymous
+    @PostMapping("/addHours")
+    public AjaxResult addHours(@RequestBody OperatingHours operatingHours){
+        Long id = operatingHoursService.insertOperatingHoursReturnId(operatingHours);
+        if (id > 0) {
+            Map<String, Long> data = new HashMap<>();
+            data.put("id", id);
+            return success(MessageUtils.message("no.action.success"), data);
+        }
+        return toAjax(id.intValue());
+    }
+    /**
+     * 修改时间段
+     * @param operatingHours
+     * @return
+     */
+    @Anonymous
+    @PostMapping("/setHours")
+    public AjaxResult setHours(@RequestBody OperatingHours operatingHours){
+        return toAjax(operatingHoursService.updateOperatingHours(operatingHours));
+    }
+
+    /**
+     * 删除时间段
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/delHours")
+    public AjaxResult delHours(@RequestParam Long id){
+        return toAjax(operatingHoursService.deleteOperatingHoursById(id));
+    }
+
+    /**
+     * 查询时间段
+     * @param mdId
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getHours")
+    public AjaxResult getHours(@RequestParam Long mdId){
+        OperatingHours operatingHours = new OperatingHours();
+        operatingHours.setMdId(mdId);
+        List<OperatingHours> list = operatingHoursService.selectOperatingHoursList(operatingHours);
+        return success(MessageUtils.message("no.obtained.success"),list);
+    }
+
+    /**
+     * 查询OperatingHours列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:hours:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(OperatingHours operatingHours)
+    {
+        startPage();
+        List<OperatingHours> list = operatingHoursService.selectOperatingHoursList(operatingHours);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出OperatingHours列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:hours:export')")
+    @Log(title = "OperatingHours", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, OperatingHours operatingHours)
+    {
+        List<OperatingHours> list = operatingHoursService.selectOperatingHoursList(operatingHours);
+        ExcelUtil<OperatingHours> util = new ExcelUtil<OperatingHours>(OperatingHours.class);
+        util.exportExcel(response, list, "OperatingHours数据");
+    }
+
+    /**
+     * 获取OperatingHours详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:hours:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(operatingHoursService.selectOperatingHoursById(id));
+    }
+
+    /**
+     * 新增OperatingHours
+     */
+    @PreAuthorize("@ss.hasPermi('system:hours:add')")
+    @Log(title = "OperatingHours", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody OperatingHours operatingHours)
+    {
+        return toAjax(operatingHoursService.insertOperatingHours(operatingHours));
+    }
+
+    /**
+     * 修改OperatingHours
+     */
+    @PreAuthorize("@ss.hasPermi('system:hours:edit')")
+    @Log(title = "OperatingHours", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody OperatingHours operatingHours)
+    {
+        return toAjax(operatingHoursService.updateOperatingHours(operatingHours));
+    }
+
+    /**
+     * 删除OperatingHours
+     */
+    @PreAuthorize("@ss.hasPermi('system:hours:remove')")
+    @Log(title = "OperatingHours", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(operatingHoursService.deleteOperatingHoursByIds(ids));
+    }
+}

+ 190 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosCollectController.java

@@ -0,0 +1,190 @@
+package com.ruoyi.app.mendian;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.utils.MessageUtils;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.domain.PosFood;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.service.IPosStoreService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.PosCollect;
+import com.ruoyi.system.service.IPosCollectService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * collectController
+ *
+ * @author ruoyi
+ * @date 2023-06-21
+ */
+@RestController
+@RequestMapping("/system/collect")
+public class PosCollectController extends BaseController
+{
+    @Autowired
+    private IPosCollectService posCollectService;
+    @Autowired
+    private IPosStoreService posStoreService;
+    /**
+     * 我的收藏门店列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getcollectlist")
+    public AjaxResult getcollectlist(@RequestHeader String token,
+                                     @RequestParam Integer page,
+                                     @RequestParam Integer size){
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosCollect> food = new Page<>(page,size);
+        QueryWrapper<PosCollect> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",id);
+        IPage<PosCollect> list = posCollectService.page(food,queryWrapper);
+        List<PosCollect> pos = list.getRecords();
+        JSONArray all = new JSONArray();
+        for(PosCollect col:pos){
+            JSONObject org = new JSONObject();
+            PosStore posStore = posStoreService.getById(col.getMdId());
+            if(posStore!=null){
+                org.put("id",posStore.getId());
+                org.put("posName",posStore.getPosName());
+                org.put("image",posStore.getImage());
+                org.put("posPrice",posStore.getPosPrice());
+                org.put("area",posStore.getArea());
+                org.put("address",posStore.getAddress());
+                org.put("longitude",posStore.getLongitude());
+                org.put("latitude",posStore.getLatitude());
+                org.put("briefIntroduction",posStore.getBriefIntroduction());
+                org.put("type",posStore.getType());
+                org.put("hygienePermit",posStore.getHygienePermit());
+                org.put("openBusiness",posStore.getOpenBusiness());
+                org.put("windingUp",posStore.getWindingUp());
+                org.put("sort",posStore.getSort());
+                org.put("userId",posStore.getUserId());
+                org.put("juli",posStore.getJuli());
+                org.put("cretim",posStore.getCretim());
+                org.put("zhitsj",posStore.getJuli());
+                org.put("tgpaixv",posStore.getCretim());
+                org.put("state",posStore.getState());
+                org.put("serverType",posStore.getServerType());
+                org.put("telephone",posStore.getTelephone());
+                org.put("offShelf",posStore.getOffShelf());
+                all.add(org);
+            }
+        }
+        return success(all);
+    }
+
+    /**
+     * 收藏或取消收藏门店
+     */
+
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @GetMapping("/addcollect")
+    public AjaxResult addcollect(@RequestHeader String token,@RequestParam Long mdid){
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<PosCollect> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",id);
+        queryWrapper.eq("md_id",mdid);
+        List<PosCollect> posCollect = posCollectService.list(queryWrapper);
+        if(posCollect.isEmpty()){
+            PosCollect collect = new PosCollect();
+            collect.setUserId(Long.valueOf(id));
+            collect.setMdId(mdid);
+            posCollectService.saveOrUpdate(collect);
+            return success(MessageUtils.message("no.collection.success"));
+        }else {
+            posCollectService.remove(queryWrapper);
+//            posCollectService.removeById(posCollect.getId());
+            return success(MessageUtils.message("no.collection.cancel"));
+        }
+    }
+
+    /**
+     * 查询collect列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:collect:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosCollect posCollect)
+    {
+        startPage();
+        List<PosCollect> list = posCollectService.selectPosCollectList(posCollect);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出collect列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:collect:export')")
+    @Log(title = "collect", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosCollect posCollect)
+    {
+        List<PosCollect> list = posCollectService.selectPosCollectList(posCollect);
+        ExcelUtil<PosCollect> util = new ExcelUtil<PosCollect>(PosCollect.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.collection"));
+    }
+
+    /**
+     * 获取collect详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:collect:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posCollectService.selectPosCollectById(id));
+    }
+
+    /**
+     * 新增collect
+     */
+    @PreAuthorize("@ss.hasPermi('system:collect:add')")
+    @Log(title = "collect", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosCollect posCollect)
+    {
+        return toAjax(posCollectService.insertPosCollect(posCollect));
+    }
+
+    /**
+     * 修改collect
+     */
+    @PreAuthorize("@ss.hasPermi('system:collect:edit')")
+    @Log(title = "collect", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosCollect posCollect)
+    {
+        return toAjax(posCollectService.updatePosCollect(posCollect));
+    }
+
+    /**
+     * 删除collect
+     */
+    @PreAuthorize("@ss.hasPermi('system:collect:remove')")
+    @Log(title = "collect", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posCollectService.deletePosCollectByIds(ids));
+    }
+}

+ 157 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosFenleiController.java

@@ -0,0 +1,157 @@
+package com.ruoyi.app.mendian;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.domain.PosFood;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.service.IPosFoodService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.PosFenlei;
+import com.ruoyi.system.service.IPosFenleiService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * spfenleiController
+ * 
+ * @author ruoyi
+ * @date 2023-05-21
+ */
+@RestController
+@RequestMapping("/system/fenlei")
+public class PosFenleiController extends BaseController
+{
+    @Autowired
+    private IPosFenleiService posFenleiService;
+    @Autowired  //商品
+    private IPosFoodService posFoodService;
+
+
+    /**
+     * 删除商品分类
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/delefenlei")
+    public AjaxResult delefenlei(@RequestParam String id){
+        QueryWrapper<PosFood> query = new QueryWrapper<>();
+        query.eq("fl_id",id);
+        List<PosFood> fdlist = posFoodService.list(query);
+        if(fdlist.size()>0){
+            return error(MessageUtils.message("no.data.exist.not.del"));
+        }else {
+            return toAjax(posFenleiService.deletePosFenleiById(Long.valueOf(id)));
+        }
+    }
+    /**
+     * 添加或修改商品分类
+     */
+    @Anonymous
+    @PostMapping("/addfenlei")
+    public AjaxResult addfenlei(@RequestBody PosFenlei posFenlei){
+        Boolean org = posFenleiService.saveOrUpdate(posFenlei);
+        if(org){
+            return success();
+        }else {
+            return error();
+        }
+
+    }
+    /**
+     * 查询商品分类
+     */
+    @Anonymous
+    @GetMapping("/getfenlei")
+    public AjaxResult getfenlei(@RequestParam Integer id,@RequestParam(defaultValue = "") String language){
+        QueryWrapper<PosFenlei> queryWrapper= new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("sort");
+        queryWrapper.eq("mendid",id);
+        String lang = "0";
+        if(!"".equals(language)){
+            lang = language;
+        }
+        queryWrapper.eq("language",lang);
+        List<PosFenlei> list = posFenleiService.list(queryWrapper);
+        return success(list);
+    }
+    /**
+     * 查询spfenlei列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:fenlei:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosFenlei posFenlei)
+    {
+        startPage();
+        List<PosFenlei> list = posFenleiService.selectPosFenleiList(posFenlei);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出spfenlei列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:fenlei:export')")
+    @Log(title = "spfenlei", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosFenlei posFenlei)
+    {
+        List<PosFenlei> list = posFenleiService.selectPosFenleiList(posFenlei);
+        ExcelUtil<PosFenlei> util = new ExcelUtil<PosFenlei>(PosFenlei.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.goods.classify"));
+    }
+
+    /**
+     * 获取spfenlei详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:fenlei:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posFenleiService.selectPosFenleiById(id));
+    }
+
+    /**
+     * 新增spfenlei
+     */
+    @PreAuthorize("@ss.hasPermi('system:fenlei:add')")
+    @Log(title = "spfenlei", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosFenlei posFenlei)
+    {
+        return toAjax(posFenleiService.insertPosFenlei(posFenlei));
+    }
+
+    /**
+     * 修改spfenlei
+     */
+    @PreAuthorize("@ss.hasPermi('system:fenlei:edit')")
+    @Log(title = "spfenlei", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosFenlei posFenlei)
+    {
+        return toAjax(posFenleiService.updatePosFenlei(posFenlei));
+    }
+
+    /**
+     * 删除spfenlei
+     */
+    @PreAuthorize("@ss.hasPermi('system:fenlei:remove')")
+    @Log(title = "spfenlei", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posFenleiService.deletePosFenleiByIds(ids));
+    }
+}

+ 442 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosFoodController.java

@@ -0,0 +1,442 @@
+package com.ruoyi.app.mendian;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.utils.ImageCompressUtils;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.InfoUser;
+import com.ruoyi.system.domain.PosFood;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.service.IPosFenleiService;
+import com.ruoyi.system.service.IPosFoodService;
+import com.ruoyi.system.service.IPosStoreService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * foodController
+ *
+ * @author ruoyi
+ * @date 2023-05-21
+ */
+@RestController
+@RequestMapping("/chanting/food")
+public class PosFoodController extends BaseController {
+    @Autowired  //商品
+    private IPosFoodService posFoodService;
+
+    @Autowired  //门店
+    private IPosStoreService posStoreService;
+
+    @Autowired //商品分类
+    private IPosFenleiService posFenleiService;
+
+    @Autowired //用户
+    private IInfoUserService infoUserService;
+
+    //删除商品
+    @Anonymous
+    @Auth
+    @GetMapping("/delefood")
+    public AjaxResult delefood(@RequestParam String id) {
+        return toAjax(posFoodService.deletePosFoodById(Long.valueOf(id)));
+    }
+
+    //推荐商品
+    @Anonymous
+    @PutMapping("/changerecommend")
+    public AjaxResult changerecommend(@RequestBody PosFood posFood) {
+        return toAjax(posFoodService.saveOrUpdate(posFood));
+    }
+
+    /**
+     * 添加或修改商品
+     */
+    @Anonymous
+    @PostMapping("/setposfood")
+    public AjaxResult setposfood(@RequestBody PosFood posFood) {
+        JSONArray jsonArray = posFood.getSku();
+        posFood.setFoodSku(jsonArray.toString());
+        Boolean org = posFoodService.saveOrUpdate(posFood);
+        if (org) {
+            return success();
+        } else {
+            return error();
+        }
+    }
+
+    /**
+     * (h5页面使用)通过分类查询商品列表
+     */
+    @Anonymous
+    @GetMapping("/h5Getidlist")
+    public AjaxResult h5Getidlist(@RequestParam Integer id, @RequestParam(defaultValue = "") String language, @RequestParam(required = false) String stackingUp) {
+        JwtUtil jwtUtil = new JwtUtil();
+//        String ids = jwtUtil.getusid(token);
+//        InfoUser user = infoUserService.getById(ids);
+        QueryWrapper<PosFood> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("fl_id", id);
+//        if(!user.getUserType().equals("1")){
+//            queryWrapper.eq("to_examine","1");
+//        }
+        if (stackingUp != null && !"".equals(stackingUp)) {
+            queryWrapper.eq("stacking_up", stackingUp);
+        }
+        String lang = "0";
+        if (!"".equals(language)) {
+            lang = language;
+        }
+        queryWrapper.eq("language", lang);
+        List<PosFood> list = posFoodService.list(queryWrapper);
+        JSONArray all = new JSONArray();
+        for (int i = 0; i < list.size(); i++) {
+            JSONObject org = new JSONObject();
+            org.put("id", list.get(i).getId());
+            org.put("fenlei", posFenleiService.getById(list.get(i).getFlId()));
+            org.put("store", posStoreService.getById(list.get(i).getMdid()));
+            org.put("name", list.get(i).getName());
+            org.put("image", list.get(i).getImage());
+            org.put("price", list.get(i).getPrice());
+            org.put("introduce", list.get(i).getIntroduce());
+            org.put("recommend", list.get(i).getRecommend());
+            org.put("foodSku", JSONArray.parseArray(list.get(i).getFoodSku()));
+            org.put("stackingUp", list.get(i).getStackingUp());
+            org.put("toExamine", list.get(i).getToExamine());
+            all.add(org);
+        }
+        return success(all);
+    }
+
+    /**
+     * 通过分类查询商品列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getidlist")
+    public AjaxResult getidlist(@RequestHeader String token, @RequestParam Integer id, @RequestParam(defaultValue = "") String language, @RequestParam(required = false) String stackingUp, @RequestParam(required = false) String name) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String ids = jwtUtil.getusid(token);
+        InfoUser user = infoUserService.getById(ids);
+        QueryWrapper<PosFood> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("fl_id", id);
+        if (!user.getUserType().equals("1")) {
+            queryWrapper.eq("to_examine", "1");
+        }
+        if (stackingUp != null && !"".equals(stackingUp)) {
+            queryWrapper.eq("stacking_up", stackingUp);
+        }
+        String lang = "0";
+        if (!"".equals(language)) {
+            lang = language;
+        }
+        queryWrapper.eq("language", lang);
+        if (name != null && !"".equals(name)) {
+            queryWrapper.apply(" BINARY name LIKE CONCAT('%', {0}, '%')", name);
+        }
+        List<PosFood> list = posFoodService.list(queryWrapper);
+        JSONArray all = new JSONArray();
+        for (int i = 0; i < list.size(); i++) {
+            JSONObject org = new JSONObject();
+            org.put("id", list.get(i).getId());
+            org.put("fenlei", posFenleiService.getById(list.get(i).getFlId()));
+            org.put("store", posStoreService.getById(list.get(i).getMdid()));
+            org.put("name", list.get(i).getName());
+            org.put("image", list.get(i).getImage());
+            org.put("price", list.get(i).getPrice());
+            org.put("introduce", list.get(i).getIntroduce());
+            org.put("recommend", list.get(i).getRecommend());
+            org.put("foodSku", JSONArray.parseArray(list.get(i).getFoodSku()));
+            org.put("stackingUp", list.get(i).getStackingUp());
+            org.put("toExamine", list.get(i).getToExamine());
+            all.add(org);
+        }
+        return success(all);
+    }
+
+    /**
+     * 查询商品详情
+     */
+    @Anonymous
+    @GetMapping("/getfood")
+    public AjaxResult getfood(@RequestParam Integer id) {
+        JSONObject org = new JSONObject();
+        PosFood posFood = posFoodService.getById(id);
+        org.put("id", posFood.getId());
+        org.put("fenlei", posFenleiService.getById(posFood.getFlId()));
+        org.put("store", posStoreService.getById(posFood.getMdid()));
+        org.put("name", posFood.getName());
+        org.put("image", posFood.getImage());
+        org.put("price", posFood.getPrice());
+        org.put("introduce", posFood.getIntroduce());
+        org.put("recommend", posFood.getRecommend());
+        org.put("stackingUp", posFood.getStackingUp());
+        org.put("foodSku", JSONArray.parseArray(posFood.getFoodSku()));
+        return success(org);
+    }
+
+    /**
+     * 搜索
+     */
+    @Anonymous
+    @GetMapping("/searchfor")
+    public AjaxResult searchfor(@RequestParam String keyword, @RequestParam(defaultValue = "") String language) {
+        if (keyword.equals("")) {
+            return error(MessageUtils.message("no.tip.lock.keywork"));
+        }
+        JSONArray all = new JSONArray();
+        JSONObject object = new JSONObject();
+        QueryWrapper<PosFood> query = new QueryWrapper<>();
+        String lang = "0";
+        if (!"".equals(language)) {
+            lang = language;
+        }
+        query.eq("language", lang);
+        query.eq("to_examine", "1");
+//        query.like("name",keyword);
+        query.apply("BINARY name LIKE CONCAT('%', {0}, '%')", keyword);
+        List<PosFood> folist = posFoodService.list(query);
+        QueryWrapper<PosStore> wrapper = new QueryWrapper<>();
+        wrapper.eq("off_shelf", "0")
+//                .and(i->i.like("pos_name", keyword).or().like("brief_introduction",keyword));
+                .and(i -> i.apply("BINARY pos_name LIKE CONCAT('%', {0}, '%')", keyword).or().apply("BINARY brief_introduction LIKE CONCAT('%', {0}, '%')", keyword));
+        List<PosStore> stlist = posStoreService.list(wrapper);
+        for (int i = 0; i < folist.size(); i++) {
+            PosStore store = posStoreService.getById(folist.get(i).getMdid());
+            if (store.getOffShelf().equals("0")) {
+                JSONObject org = new JSONObject();
+                org.put("id", folist.get(i).getId());
+                org.put("fenlei", posFenleiService.getById(folist.get(i).getFlId()));
+                org.put("store", posStoreService.getById(folist.get(i).getMdid()));
+                org.put("name", folist.get(i).getName());
+                org.put("image", folist.get(i).getImage());
+                org.put("price", folist.get(i).getPrice());
+                org.put("introduce", folist.get(i).getIntroduce());
+                org.put("recommend", folist.get(i).getRecommend());
+                org.put("stackingUp", folist.get(i).getStackingUp());
+                org.put("foodSku", JSONArray.parseArray(folist.get(i).getFoodSku()));
+                all.add(org);
+            }
+        }
+        object.put("food", all);
+        object.put("store", stlist);
+        return success(object);
+    }
+
+
+    @Anonymous
+    @GetMapping("/getFoodPageList")
+    public AjaxResult getFoodPageList(@RequestHeader String token,
+                                      @RequestParam Integer page,
+                                      @RequestParam Integer size,
+                                      @RequestParam Long flId,
+                                      @RequestParam Long mdId,
+                                      @RequestParam(defaultValue = "") String language,
+                                      @RequestParam(defaultValue = "") String name) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosFood> stlist = new Page<>(page, size);
+        LambdaQueryWrapper<PosFood> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PosFood::getFlId, flId);
+        queryWrapper.eq(PosFood::getMdid, mdId);
+
+        // language 不为 null 且不为空字符串时才加条件
+        if (language != null && !"".equals(language)) {
+            queryWrapper.eq(PosFood::getLanguage, language);
+        }
+
+        // name 不为 null 且不为空字符串时模糊查询
+        if (name != null && !"".equals(name)) {
+            queryWrapper.like(PosFood::getName, name);
+        }
+
+        IPage<PosFood> list = posFoodService.page(stlist, queryWrapper);
+        return success(list);
+    }
+
+    /**
+     * 查询商品列表
+     */
+    @Anonymous
+    @GetMapping("/getfoodlist")
+    public AjaxResult getfoodlist(@RequestParam Integer page,
+                                  @RequestParam Integer size,
+                                  @RequestParam(defaultValue = "") String language,
+                                  @RequestParam(defaultValue = "") String keyword) {
+        IPage<PosFood> food = new Page<>(page, size);
+        QueryWrapper<PosFood> queryWrapper = new QueryWrapper<>();
+        String lang = "0";
+        if (!"".equals(language)) {
+            lang = language;
+        }
+        queryWrapper.eq("language", lang);
+        queryWrapper.eq("to_examine", "1");
+        if (!"".equals(keyword)) {
+            queryWrapper.like("name", keyword);
+        }
+        IPage<PosFood> list = posFoodService.page(food, queryWrapper);
+        List<PosFood> foodlist = list.getRecords();
+        JSONArray all = new JSONArray();
+        for (int i = 0; i < foodlist.size(); i++) {
+            PosStore store = posStoreService.getById(foodlist.get(i).getMdid());
+            if (store.getOffShelf().equals("0")) {
+                JSONObject org = new JSONObject();
+                org.put("id", foodlist.get(i).getId());
+                org.put("fenlei", posFenleiService.getById(foodlist.get(i).getFlId()));
+                org.put("store", posStoreService.getById(foodlist.get(i).getMdid()));
+                org.put("name", foodlist.get(i).getName());
+                org.put("image", foodlist.get(i).getImage());
+                org.put("price", foodlist.get(i).getPrice());
+                org.put("introduce", foodlist.get(i).getIntroduce());
+                org.put("recommend", foodlist.get(i).getRecommend());
+                org.put("stackingUp", foodlist.get(i).getStackingUp());
+                org.put("foodSku", JSONArray.parseArray(foodlist.get(i).getFoodSku()));
+                all.add(org);
+            }
+        }
+        return success(all);
+    }
+
+    /**
+     * 查询food列表
+     */
+
+    @PreAuthorize("@ss.hasPermi('chanting:food:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosFood posFood) {
+        startPage();
+        List<PosFood> list = posFoodService.selectPosFoodList(posFood);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出food列表
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:food:export')")
+    @Log(title = "food", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosFood posFood) {
+        List<PosFood> list = posFoodService.selectPosFoodList(posFood);
+        ExcelUtil<PosFood> util = new ExcelUtil<PosFood>(PosFood.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.food"));
+    }
+
+    /**
+     * 获取food详细信息
+     */
+    @Anonymous
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(posFoodService.selectPosFoodById(id));
+    }
+
+    /**
+     * 新增food
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:food:add')")
+    @Log(title = "food", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosFood posFood) {
+        return toAjax(posFoodService.insertPosFood(posFood));
+    }
+
+    /**
+     * 修改food
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:food:edit')")
+    @Log(title = "food", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosFood posFood) {
+        return toAjax(posFoodService.updatePosFood(posFood));
+    }
+
+    /**
+     * 删除food
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:food:remove')")
+    @Log(title = "food", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(posFoodService.deletePosFoodByIds(ids));
+    }
+
+    /**
+     * 压缩图片店铺的商品图片
+     */
+    @Anonymous
+    @GetMapping("/compressFoodImage")
+    public AjaxResult compressFoodImage(@RequestParam Long mdId, @RequestParam String idsStr) {
+        LambdaQueryWrapper<PosFood> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PosFood::getMdid, mdId);
+        List<Long> ids= new ArrayList<>();
+        if(!StringUtils.isEmpty(idsStr)){
+            ids = Arrays.stream(idsStr.split(","))
+                    .map(Long::valueOf)
+                    .collect(Collectors.toList());
+        }
+        queryWrapper.in(!ids.isEmpty(), PosFood::getId, ids);
+        List<PosFood> list = posFoodService.list(queryWrapper);
+        AtomicInteger count = new AtomicInteger();
+        list.forEach(food -> {
+            String compressImage = ImageCompressUtils.compressImageByWebPath(food.getImage());
+            if (!compressImage.equals(food.getImage())) {
+                food.setImage(compressImage);
+                PosFood posFood = new PosFood();
+                posFood.setId(food.getId());
+                posFood.setImage(compressImage);
+                posFoodService.saveOrUpdate(posFood);
+                count.getAndIncrement();
+                System.out.println("food成功压缩的图片数量:"+count.get());
+                logger.info("food成功压缩的图片数量:"+count.get());
+            }
+        });
+        return success("成功压缩的 :"+count.get());
+    }
+
+    /**
+     * 压缩所有的商品图片
+     */
+    @Anonymous
+    @GetMapping("/compressFoodImageAll")
+    public AjaxResult compressFoodImage() {
+        LambdaQueryWrapper<PosFood> queryWrapper = new LambdaQueryWrapper<>();
+        List<PosFood> list = posFoodService.list(queryWrapper);
+        AtomicInteger count = new AtomicInteger();
+        list.forEach(food -> {
+            String compressImage = ImageCompressUtils.compressImageByWebPath(food.getImage());
+            if (!compressImage.equals(food.getImage())) {
+                food.setImage(compressImage);
+                PosFood posFood = new PosFood();
+                posFood.setId(food.getId());
+                posFood.setImage(compressImage);
+                posFoodService.saveOrUpdate(posFood);
+                count.getAndIncrement();
+                System.out.println("food成功压缩的图片数量:"+count.get());
+                logger.info("food成功压缩的图片数量:"+count.get());
+            }
+        });
+        return success("成功压缩的图片数量:"+count.get());
+    }
+}

+ 402 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java

@@ -0,0 +1,402 @@
+package com.ruoyi.app.mendian;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.ImageCompressUtils;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.mapper.PosStoreMapper;
+import com.ruoyi.system.mapper.SysConfigMapper;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * posstoreController
+ *
+ * @author ruoyi
+ * @date 2023-05-14
+ */
+@RestController
+@RequestMapping("/chanting/store")
+public class PosStoreController extends BaseController
+{
+    @Autowired
+    private IPosStoreService posStoreService;
+
+    @Autowired
+    private PosStoreMapper posStoreMapper;
+    @Autowired
+    private IPosCollectService posCollectService;
+    @Autowired
+    private IPosFenleiService posFenleiService;
+
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IOperatingHoursService operatingHoursService;
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+
+    /**
+     * 根据评分查旬门店
+     * @param longitude
+     * @param latitude
+     * @param page
+     * @param juli
+     * @param type
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getPfStore")
+    public AjaxResult getPfStore(@RequestParam BigDecimal longitude,
+                                    @RequestParam BigDecimal latitude,
+                                    @RequestParam Integer page,
+                                    @RequestParam Integer juli,
+                                    @RequestParam Integer type)
+    {
+        if(type==0){
+            List<PosStore> list = posStoreMapper.getPingfStore(longitude,latitude,(page-1)*10,juli);
+            return success(list);
+        }else if(type==1){
+            List<PosStore> list = posStoreMapper.getReduStore(longitude,latitude,(page-1)*10,juli);
+            return success(list);
+        }else {
+            List<PosStore> list = posStoreMapper.getNewStore(longitude,latitude,(page-1)*10,juli);
+            return success(list);
+        }
+    }
+
+    //删除我的门店
+    @Anonymous
+    @Auth
+    @GetMapping("/delemendian")
+    public AjaxResult delemendian(@RequestParam String id){
+        QueryWrapper<PosFenlei> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("mendid",id);
+        List<PosFenlei> list = posFenleiService.list(queryWrapper);
+        if(list.size()>0){
+            return error(MessageUtils.message("no.mendian.exist.classify.not.del"));
+        }else {
+            return toAjax(posStoreService.deletePosStoreById(Long.valueOf(id)));
+        }
+    }
+
+    /**
+     * H5端门店列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/storelistlist")
+    public AjaxResult storelistlist(@RequestHeader String token,
+                                    @RequestParam Integer page,
+                                    @RequestParam Integer size)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosStore> stlist = new Page<>(page,size);
+        QueryWrapper<PosStore> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("user_id",id);
+        IPage<PosStore> list =  posStoreService.page(stlist,queryWrapper);
+        if(!list.getRecords().isEmpty()){
+            QueryWrapper<OperatingHours> wrapper = new QueryWrapper<>();
+            wrapper.in("md_id",list.getRecords().stream().map(PosStore::getId).collect(Collectors.toList()));
+            List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
+            list.getRecords().forEach(posStore -> {
+                posStore.setBusinessHours(hourslist);
+            });
+        }
+
+        return success(list);
+    }
+    //查询我的门店列表
+    @Anonymous
+    @Auth
+    @GetMapping("/getmystorelist")
+    public AjaxResult getmystorelist(@RequestHeader String token){
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<PosStore> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",id);
+        List<PosStore> list = posStoreService.list(queryWrapper);
+        return success(list);
+    }
+
+    //查询门店列表
+    @Anonymous
+    @GetMapping("/getstore")
+    public AjaxResult getstore(@RequestHeader(defaultValue = "") String token,@RequestParam Integer id){
+        if(!"".equals(token)){
+            JwtUtil jwtUtil = new JwtUtil();
+            String usid = jwtUtil.getusid(token);
+            QueryWrapper<PosCollect> queryWrapper= new QueryWrapper<>();
+            queryWrapper.eq("user_id",usid);
+            queryWrapper.eq("md_id",id);
+            List<PosCollect> list = posCollectService.list(queryWrapper);
+            PosStore posStore = posStoreService.getById(id);
+            JSONObject org = new JSONObject();
+            org.put("id",posStore.getId());
+            org.put("posName",posStore.getPosName());
+            org.put("image",posStore.getImage());
+            org.put("posPrice",posStore.getPosPrice());
+            org.put("area",posStore.getArea());
+            org.put("address",posStore.getAddress());
+            org.put("longitude",posStore.getLongitude());
+            org.put("latitude",posStore.getLatitude());
+            org.put("briefIntroduction",posStore.getBriefIntroduction());
+            org.put("type",posStore.getType());
+            org.put("hygienePermit",posStore.getHygienePermit());
+            org.put("hygieneLicence",posStore.getHygieneLicence());
+            org.put("openBusiness",posStore.getOpenBusiness());
+            org.put("windingUp",posStore.getWindingUp());
+            org.put("sort",posStore.getSort());
+            org.put("userId",posStore.getUserId());
+            org.put("juli",posStore.getJuli());
+            org.put("cretim",posStore.getCretim());
+            org.put("zhitsj",posStore.getJuli());
+            org.put("tgpaixv",posStore.getCretim());
+            org.put("state",posStore.getState());
+            org.put("serverType",posStore.getServerType());
+            org.put("telephone",posStore.getTelephone());
+            org.put("Collect", !list.isEmpty() ?1:0);
+            org.put("logo",posStore.getLogo());
+
+            QueryWrapper<OperatingHours> wrapper = new QueryWrapper<>();
+            wrapper.eq("md_id", posStore.getId());
+            List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
+            DateUtil dateUtil = new DateUtil();
+            Boolean dayang = false;
+            //在营业时间范围内返回true
+            for (int i = 0; i < hourslist.size(); i++) {
+                Boolean sbsj = dateUtil.isLegalTime(hourslist.get(i).getStartTime(), hourslist.get(i).getEndTime());
+                if (sbsj == true) {
+                    dayang = true;
+                }
+            }
+            //不在时间范围内标识为打烊
+            if (dayang == false) {
+                org.put("state",1);
+            }
+            org.put("businessHours", hourslist);
+            return success(org);
+        }else {
+            PosStore posStore = posStoreService.getById(id);
+            return success(posStore);
+        }
+
+
+    }
+    //根据行业分类查询门店列表
+    @Anonymous
+    @GetMapping("/getstorelist")
+    public AjaxResult getstorelist(@RequestParam BigDecimal longitude,
+                                   @RequestParam BigDecimal latitude,
+                                   @RequestParam Integer page,
+                                   @RequestParam String area,
+                                   @RequestParam Integer juli,
+                                   @RequestParam(defaultValue = "") Integer sort)
+    {
+        if(sort==null){
+            List<PosStore> list = posStoreMapper.getmdlist(longitude,latitude,(page-1)*20,"%"+area+"%",juli);
+
+            return success(list);
+        }else {
+            List<PosStore> list = posStoreMapper.getdaidiq(longitude,latitude,(page-1)*20,"%"+area+"%",juli,sort);
+            return success(list);
+        }
+
+
+    }
+    //根据服务分类查询门店列表
+    @Anonymous
+    @GetMapping("/getserverlist")
+    public AjaxResult getserverlist(@RequestParam BigDecimal longitude,
+                                   @RequestParam BigDecimal latitude,
+                                   @RequestParam Integer page,
+                                   @RequestParam String area,
+                                   @RequestParam Integer juli,
+                                   @RequestParam(defaultValue = "") String serverType)
+    {
+        if(!"".equals(serverType)){
+            List<PosStore> list = posStoreMapper.getserverlist(longitude,latitude,(page-1)*20,"%"+area+"%",juli,"%"+serverType+"%");
+            return success(list);
+        }else {
+            List<PosStore> list = posStoreMapper.getmdlist(longitude,latitude,(page-1)*20,"%"+area+"%",juli);
+            return success(list);
+        }
+
+    }
+    //添加门店
+    @Anonymous
+    @PostMapping("/addmendian")
+    @Transactional
+    public AjaxResult addmendian(@RequestBody PosStore posStore)
+    {
+        Boolean org = posStoreService.saveOrUpdate(posStore);
+
+        if(org){
+            QueryWrapper<PosStore> wrapper = new QueryWrapper<>();
+            wrapper.eq("pos_name",posStore.getPosName());
+            wrapper.eq("user_id",posStore.getUserId());
+            PosStore store = posStoreService.getOne(wrapper);
+
+            if(posStore.getBusinessHours()!=null && posStore.getBusinessHours().size()>0){
+                LambdaQueryWrapper<OperatingHours> query = new LambdaQueryWrapper<>();
+                query.eq(OperatingHours::getMdId,Long.valueOf(store.getId()));
+                operatingHoursService.remove( query);
+                posStore.getBusinessHours().forEach(operatingHours -> {
+                    operatingHours.setMdId(Long.valueOf(store.getId()));
+                });
+                operatingHoursService.saveBatch(posStore.getBusinessHours());
+            }
+            return success(MessageUtils.message("no.success"),store);
+        }else {
+            return error();
+        }
+
+    }
+    /**
+     * 查询posstore列表
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:store:list')")
+//    @Anonymous
+    @GetMapping("/list")
+    public TableDataInfo list(PosStore posStore)
+    {
+        startPage();
+        List<PosStore> list = posStoreService.selectPosStoreList(posStore);
+        for (PosStore store:list){
+            InfoUser user = infoUserService.getById(store.getUserId());
+            store.setUserName(user.getUserName());
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出posstore列表
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:store:export')")
+    @Log(title = "posstore", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosStore posStore)
+    {
+        List<PosStore> list = posStoreService.selectPosStoreList(posStore);
+        ExcelUtil<PosStore> util = new ExcelUtil<PosStore>(PosStore.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.posstore"));
+    }
+
+    /**
+     * 获取posstore详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:store:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posStoreService.selectPosStoreById(id));
+    }
+
+    /**
+     * 新增posstore
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:store:add')")
+    @Log(title = "posstore", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosStore posStore)
+    {
+        return toAjax(posStoreService.insertPosStore(posStore));
+    }
+
+    /**
+     * 修改posstore
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:store:edit')")
+    @Log(title = "posstore", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosStore posStore)
+    {
+        return toAjax(posStoreService.updatePosStore(posStore));
+    }
+    /**
+     * 修改posstore下架状态
+     */
+    @Anonymous
+    @PutMapping("/changeOffShelf")
+    public AjaxResult changeOffShelf(@RequestBody PosStore posStore)
+    {
+        Boolean res = posStoreService.saveOrUpdate(posStore);
+        if (res){
+            return success();
+        }else {
+            return error();
+        }
+
+    }
+    /**
+     * 删除posstore
+     */
+    @PreAuthorize("@ss.hasPermi('chanting:store:remove')")
+    @Log(title = "posstore", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posStoreService.deletePosStoreByIds(ids));
+    }
+
+    /**
+     * 压缩图片店铺的商品图片
+     */
+    @Anonymous
+    @GetMapping("/compressStoreImage")
+    public AjaxResult compressStoreImage(@RequestParam String idsStr) {
+        LambdaQueryWrapper<PosStore> queryWrapper = new LambdaQueryWrapper<>();
+
+        List<Integer> ids= new ArrayList<>();
+        if(!StringUtils.isEmpty(idsStr)){
+            ids = Arrays.stream(idsStr.split(","))
+                    .map(Integer::valueOf)
+                    .collect(Collectors.toList());
+        }
+        queryWrapper.in(!ids.isEmpty(), PosStore::getId, ids);
+        List<PosStore> list = posStoreService.list(queryWrapper);
+        AtomicInteger count = new AtomicInteger();
+        list.forEach(food -> {
+            String compressImage = ImageCompressUtils.compressImageByWebPath(food.getImage());
+            if (!compressImage.equals(food.getImage())) {
+                food.setImage(compressImage);
+                PosStore posStore = new PosStore();
+                posStore.setId(food.getId());
+                posStore.setImage(compressImage);
+                posStoreService.saveOrUpdate(posStore);
+                count.getAndIncrement();
+                System.out.println("store成功压缩的图片数量:"+count.get());
+                logger.info("store成功压缩的图片数量:"+count.get());
+            }
+        });
+        return success("成功压缩的图片数量:"+count.get());
+    }
+
+}

+ 117 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosTypeController.java

@@ -0,0 +1,117 @@
+package com.ruoyi.app.mendian;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.utils.MessageUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.PosType;
+import com.ruoyi.system.service.IPosTypeService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 门店分类Controller
+ * 
+ * @author ruoyi
+ * @date 2023-05-13
+ */
+@RestController
+@RequestMapping("/fenlei/type")
+public class PosTypeController extends BaseController
+{
+    @Autowired
+    private IPosTypeService posTypeService;
+
+    /**
+     * 查询门店分类列表
+     */
+    @Anonymous
+    @GetMapping("/typelist")
+    public AjaxResult typelist(PosType posType)
+    {
+        List<PosType> list = posTypeService.selectPosTypeList(posType);
+        return success(MessageUtils.message("no.obtained.permission"),list);
+    }
+    /**
+     * 查询门店分类列表
+     */
+    @Anonymous
+    @GetMapping("/list")
+    public TableDataInfo list(PosType posType)
+    {
+        startPage();
+        List<PosType> list = posTypeService.selectPosTypeList(posType);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出门店分类列表
+     */
+    @PreAuthorize("@ss.hasPermi('fenlei:type:export')")
+    @Log(title = "门店分类", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosType posType)
+    {
+        List<PosType> list = posTypeService.selectPosTypeList(posType);
+        ExcelUtil<PosType> util = new ExcelUtil<PosType>(PosType.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.mendian.classify"));
+    }
+
+    /**
+     * 获取门店分类详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fenlei:type:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posTypeService.selectPosTypeById(id));
+    }
+
+    /**
+     * 新增门店分类
+     */
+    @PreAuthorize("@ss.hasPermi('fenlei:type:add')")
+    @Log(title = "门店分类", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosType posType)
+    {
+        return toAjax(posTypeService.insertPosType(posType));
+    }
+
+    /**
+     * 修改门店分类
+     */
+    @PreAuthorize("@ss.hasPermi('fenlei:type:edit')")
+    @Log(title = "门店分类", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosType posType)
+    {
+        return toAjax(posTypeService.updatePosType(posType));
+    }
+
+    /**
+     * 删除门店分类
+     */
+    @PreAuthorize("@ss.hasPermi('fenlei:type:remove')")
+    @Log(title = "门店分类", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posTypeService.deletePosTypeByIds(ids));
+    }
+}

+ 116 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ServiceTypeController.java

@@ -0,0 +1,116 @@
+package com.ruoyi.app.mendian;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.annotation.Anonymous;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.ServiceType;
+import com.ruoyi.system.service.IServiceTypeService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * ServiceTypeController
+ * 
+ * @author ruoyi
+ * @date 2024-02-24
+ */
+@RestController
+@RequestMapping("/system/ServiceType")
+public class ServiceTypeController extends BaseController
+{
+    @Autowired
+    private IServiceTypeService serviceTypeService;
+
+    //获取服务类型列表
+    @Anonymous
+    @GetMapping("/fwlxlist")
+    public TableDataInfo fwlxlist(ServiceType serviceType)
+    {
+        startPage();
+        List<ServiceType> list = serviceTypeService.selectServiceTypeList(serviceType);
+        return getDataTable(list);
+    }
+    /**
+     * 查询ServiceType列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:ServiceType:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(ServiceType serviceType)
+    {
+        startPage();
+        List<ServiceType> list = serviceTypeService.selectServiceTypeList(serviceType);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出ServiceType列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:ServiceType:export')")
+    @Log(title = "ServiceType", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ServiceType serviceType)
+    {
+        List<ServiceType> list = serviceTypeService.selectServiceTypeList(serviceType);
+        ExcelUtil<ServiceType> util = new ExcelUtil<ServiceType>(ServiceType.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.servicetype"));
+    }
+
+    /**
+     * 获取ServiceType详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:ServiceType:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(serviceTypeService.selectServiceTypeById(id));
+    }
+
+    /**
+     * 新增ServiceType
+     */
+    @PreAuthorize("@ss.hasPermi('system:ServiceType:add')")
+    @Log(title = "ServiceType", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ServiceType serviceType)
+    {
+        return toAjax(serviceTypeService.insertServiceType(serviceType));
+    }
+
+    /**
+     * 修改ServiceType
+     */
+    @PreAuthorize("@ss.hasPermi('system:ServiceType:edit')")
+    @Log(title = "ServiceType", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody ServiceType serviceType)
+    {
+        return toAjax(serviceTypeService.updateServiceType(serviceType));
+    }
+
+    /**
+     * 删除ServiceType
+     */
+    @PreAuthorize("@ss.hasPermi('system:ServiceType:remove')")
+    @Log(title = "ServiceType", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(serviceTypeService.deleteServiceTypeByIds(ids));
+    }
+}

+ 110 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShPosReviewController.java

@@ -0,0 +1,110 @@
+package com.ruoyi.app.mendian;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.PosReview;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.service.IPosReviewService;
+import com.ruoyi.system.service.IPosStoreService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 门店订单评论
+ */
+@RestController
+@RequestMapping("/system/shPosReview")
+public class ShPosReviewController extends BaseController{
+    @Autowired
+    private IPosReviewService posReviewService;
+    @Autowired
+    private IPosStoreService  posStoreService;
+
+
+    /**
+     * 查询review列表
+     */
+    @Auth
+    @GetMapping("/list")
+    public AjaxResult list(@RequestHeader String token,
+                              @RequestParam Integer page,
+                              @RequestParam Integer size)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        List<PosStore> stores=posStoreService.list(new LambdaQueryWrapper<>(PosStore.class).eq(PosStore::getUserId,id));
+        List<Integer> mdIds=stores.stream().map(PosStore::getId).collect(Collectors.toList());
+        IPage<PosReview> palist = new Page<>(page,size);
+        LambdaQueryWrapper<PosReview> Wrapper= new LambdaQueryWrapper<>();
+        Wrapper.in(PosReview::getMdId,mdIds);
+        IPage<PosReview> list =  posReviewService.page(palist,Wrapper);
+        return success(list);
+    }
+
+//    /**
+//     * 导出review列表
+//     */
+//
+//
+//    @Log(title = "review", businessType = BusinessType.EXPORT)
+//    @PostMapping("/export")
+//    public void export(HttpServletResponse response, PosReview posReview)
+//    {
+//        List<PosReview> list = posReviewService.selectPosReviewList(posReview);
+//        ExcelUtil<PosReview> util = new ExcelUtil<PosReview>(PosReview.class);
+//        util.exportExcel(response, list, MessageUtils.message("no.export.excel.review"));
+//    }
+
+    /**
+     * 获取review详细信息
+     */
+
+    @Anonymous
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posReviewService.selectPosReviewById(id));
+    }
+
+
+
+    /**
+     * 修改review
+     */
+
+    @Log(title = "review", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosReview posReview)
+    {
+        return toAjax(posReviewService.updatePosReview(posReview));
+    }
+
+    /**
+     * 删除review
+     */
+
+    @Log(title = "review", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posReviewService.deletePosReviewByIds(ids));
+    }
+}

+ 204 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShQuanyiController.java

@@ -0,0 +1,204 @@
+package com.ruoyi.app.mendian;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.GetVipqy;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.service.IPosStoreService;
+import com.ruoyi.system.service.IVipQuanyiService;
+import com.ruoyi.system.service.IVipUserQuanyiService;
+import com.ruoyi.system.service.IVipUserService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 商家端优惠券管理Controller
+ *
+ * @author ruoyi
+ * @date 2023-05-21
+ */
+@RestController
+@RequestMapping("/system/shQuanyi")
+public class ShQuanyiController extends BaseController {
+    @Autowired
+    private IVipQuanyiService vipQuanyiService;
+    @Autowired
+    private IVipUserService vipUserService;
+    @Autowired
+    private IVipUserQuanyiService vipUserQuanyiService;
+
+    @Autowired
+    private IPosStoreService storeService;
+
+    @Anonymous
+    @Auth
+    @GetMapping("/getMyquanyi")
+    public AjaxResult getMyquanyi(@RequestHeader String token) {
+        JwtUtil jwtUtil = new JwtUtil();
+        DateUtil date = new DateUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<VipUser> Wrapper = new QueryWrapper<>();
+        Wrapper.eq("user_id", id);
+        Wrapper.apply("date_format (yxtim,'%Y-%m-%d') >= date_format ({0},'%Y-%m-%d')", date.GetDate());
+        VipUser user = vipUserService.getOne(Wrapper);
+        if (user == null) {
+            return error(MessageUtils.message("no.user.not.vip"));
+        } else {
+            GetVipqy quany = new GetVipqy();
+            List<VipQuanyi> list = quany.getvipqy(id);
+            List<VipQuanyi> qulist = new ArrayList<>();
+            for (int i = 0; i < list.size(); i++) {
+                VipQuanyi vip = new VipQuanyi();
+                if (list.get(i).getNum() > 0) {
+                    vip.setId(list.get(i).getId());
+                    vip.setName(list.get(i).getName());
+                    vip.setNum(list.get(i).getNum());
+                    vip.setVip(list.get(i).getVip());
+                    vip.setShuoming(list.get(i).getShuoming());
+                    vip.setTiaojian(list.get(i).getTiaojian());
+                    vip.setYhfangs(list.get(i).getYhfangs());
+                    vip.setYhnum(list.get(i).getYhnum());
+                    qulist.add(vip);
+                }
+            }
+            return success(qulist);
+        }
+
+    }
+
+    /**
+     * 查询商家优惠券列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/list")
+    public AjaxResult list(@RequestHeader String token,
+                           @RequestParam Integer page,
+                           @RequestParam Integer size,
+                           @RequestParam String language,
+                           @RequestParam Long shId
+    ) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<VipQuanyi> iPage = new Page<>(page, size);
+        LambdaQueryWrapper<VipQuanyi> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(VipQuanyi::getShId, shId);
+        queryWrapper.eq(VipQuanyi::getType,"1");
+        queryWrapper.eq(VipQuanyi::getLanguage, language);
+        queryWrapper.eq(VipQuanyi::getDeleted, "0");
+        IPage<VipQuanyi> list = vipQuanyiService.page(iPage, queryWrapper);
+        return success(list);
+    }
+
+
+    /**
+     * 获取商家优惠券详细信息
+     */
+    @Anonymous
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        VipQuanyi result= vipQuanyiService.selectVipQuanyiById(id);
+        if(result!=null){
+            LambdaQueryWrapper<VipUserQuanyi> query= new LambdaQueryWrapper<>();
+            query.eq(VipUserQuanyi::getQuanyiId,id);
+            boolean exist = vipUserQuanyiService.count(query) > 0;
+            if(exist){
+                result.setEdit(!exist);
+            }else{
+                result.setEdit(true);
+            }
+        }
+        return success(result);
+    }
+
+    /**
+     * 新增商家优惠券
+     */
+    @Anonymous
+    @Auth
+    @PostMapping
+    public AjaxResult add(@RequestHeader String token, @RequestBody VipQuanyi vipQuanyi) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+//        vipQuanyi.setShId(Long.valueOf(id));
+        vipQuanyi.setCreateTime(new Date());
+        vipQuanyi.setType("1");
+        vipQuanyi.setMerchantId(Long.valueOf(id));
+        return toAjax(vipQuanyiService.insertVipQuanyi(vipQuanyi));
+    }
+
+    /**
+     * 修改优惠券
+     */
+    @Anonymous
+    @Auth
+    @PutMapping
+    public AjaxResult edit(@RequestBody VipQuanyi vipQuanyi) {
+        vipQuanyi.setUpdateTime(new Date());
+        return toAjax(vipQuanyiService.updateVipQuanyi(vipQuanyi));
+    }
+
+    /**
+     * 删除优惠券
+     */
+    @Anonymous
+    @Auth
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(vipQuanyiService.deleteVipQuanyiByIds(ids));
+    }
+
+    /**
+     * 补充优惠券商家id
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/setMerchatId")
+    public AjaxResult  setMerchatId () {
+        List<VipQuanyi> list = vipQuanyiService.list(new LambdaQueryWrapper<VipQuanyi>().isNotNull(VipQuanyi::getShId).isNull(VipQuanyi::getMerchantId).eq(VipQuanyi::getType,"1"));
+        if(!list.isEmpty()){
+            List<Long> storeIds = list.stream().map(VipQuanyi::getShId).collect(Collectors.toList());
+            LambdaQueryWrapper<PosStore> query= new LambdaQueryWrapper<>();
+            query.in(PosStore::getId,storeIds);
+            List<PosStore> stores = storeService.list(query);
+            list.forEach(item->{
+                stores.stream().filter(m->Long.valueOf(m.getId()).equals(item.getShId())).findFirst().ifPresent(m->item.setMerchantId(m.getUserId()));
+                vipQuanyiService.updateById(item);
+            });
+        }
+        List<VipUserQuanyi> list2 = vipUserQuanyiService.list(new LambdaQueryWrapper<VipUserQuanyi>().isNotNull(VipUserQuanyi::getShId).isNull(VipUserQuanyi::getMerchantId).eq(VipUserQuanyi::getType,"1"));
+        if(!list2.isEmpty()){
+            List<Long> storeIds = list2.stream().map(VipUserQuanyi::getShId).collect(Collectors.toList());
+            LambdaQueryWrapper<PosStore> query= new LambdaQueryWrapper<>();
+            query.in(PosStore::getId,storeIds);
+            List<PosStore> stores = storeService.list(query);
+            list2.forEach(item->{
+                stores.stream().filter(m->Long.valueOf(m.getId()).equals(item.getShId())).findFirst().ifPresent(m->item.setMerchantId(m.getUserId()));
+                vipUserQuanyiService.updateById(item);
+            });
+        }
+        return AjaxResult.success();
+    }
+}
+
+

+ 214 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShSalesPromotionController.java

@@ -0,0 +1,214 @@
+package com.ruoyi.app.mendian;
+
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.domain.SalesPromotion;
+import com.ruoyi.system.domain.VipUserQuanyi;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.service.ISalesPromotionService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+
+/**
+ * 商家端促销活动管理
+ */
+@RestController
+@RequestMapping("/system/shSalesPromotion")
+public class ShSalesPromotionController  extends BaseController {
+    @Autowired
+    private ISalesPromotionService salesPromotionService;
+
+    @Autowired
+    private PosOrderMapper posOrderMapper;
+    /**
+     * 获取可参于促销活动
+     * @param mdId
+     * @param price
+     * @param yfPrice
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getorderuzt")
+    public AjaxResult getorderuzt(@RequestHeader String token ,
+                                  @RequestParam(defaultValue = "") String mdId,
+                                  @RequestParam(defaultValue = "") String price,
+                                  @RequestParam(defaultValue = "") String yfPrice)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        DateUtil date = new DateUtil();
+        QueryWrapper<SalesPromotion> wrapper = new QueryWrapper<>();
+        //传0 表示自提,去掉运费优惠券
+        if(yfPrice.equals("0")){
+            wrapper.ne("sales_type", "1");
+        }
+        wrapper.eq("sales_state",0);
+        wrapper.ge("end_time",date.GetDateNt());
+        if(!"".equals(mdId)){
+            wrapper.and(wra->wra.eq("sh_id",mdId).or().isNull("sh_id"));
+        }else {
+            wrapper.isNull("sh_id");
+        }
+
+        // 动态构建价格条件
+        boolean hasPrice = StringUtils.isNotBlank(price);
+        boolean hasYfPrice = StringUtils.isNotBlank(yfPrice);
+
+        if (hasPrice || hasYfPrice) {
+            wrapper.and(sub -> {
+                if (hasPrice) {
+                    sub.and(subWrapper ->
+                            subWrapper.le("sales_condition", price)
+                                    .ne("sales_type", "1")
+                    ).or(subWrapper ->
+                            subWrapper.isNull("sales_condition")
+                                    .ne("sales_type", "1")
+                    );
+                }
+                if (hasYfPrice) {
+                    if (hasPrice) { // 当两者都存在时添加 OR
+                        sub.or(subWrapper ->
+                                subWrapper.le("sales_condition", yfPrice)
+                                        .eq("sales_type", "1")
+                        ).or(subWrapper ->
+                                subWrapper.isNull("sales_condition")
+                                        .eq("sales_type", "1")
+                        );
+                    }else{
+                        sub.and(subWrapper ->
+                                subWrapper.le("sales_condition", yfPrice)
+                                        .eq("sales_type", "1")
+                        ).or(subWrapper ->
+                                subWrapper.isNull("sales_condition")
+                                        .eq("sales_type", "1")
+                        );
+                    }
+
+                }
+            });
+        }
+
+        List<SalesPromotion> saleslist = salesPromotionService.list(wrapper);
+        JSONArray array = new JSONArray();
+        for (int i=0;i<saleslist.size();i++){
+            if(saleslist.get(i).getSalesFund()==null){
+                array.add(saleslist.get(i));
+            }else {
+                int sycs = posOrderMapper.getActivity(Long.valueOf(id),saleslist.get(i).getId());
+                int fund = Math.toIntExact(saleslist.get(i).getSalesFund());
+                //促销活动开启了每个用户使用次数,使用次数小于限制才能返回
+                if(sycs<fund){
+                    array.add(saleslist.get(i));
+                }
+            }
+        }
+        return success(array);
+    }
+    /**
+     * 查询查询商家促销列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/list")
+    public AjaxResult list(@RequestHeader String token,
+                              @RequestParam Integer page,
+                              @RequestParam Integer size,
+                           @RequestParam String language,
+                           @RequestParam Long shId
+    )
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<SalesPromotion> stlist = new Page<>(page,size);
+        LambdaQueryWrapper<SalesPromotion> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SalesPromotion::getDeleted,'0');
+        queryWrapper.eq(SalesPromotion::getShId,shId);
+        queryWrapper.eq(SalesPromotion::getLanguage,language);
+        IPage<SalesPromotion> list =  salesPromotionService.page(stlist,queryWrapper);
+        return success(list);
+    }
+
+
+    /**
+     * 获取促销活动详细信息
+     */
+    @Anonymous
+    @Auth
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        SalesPromotion result= salesPromotionService.selectSalesPromotionById(id);
+        if(result!=null) {
+            LambdaQueryWrapper<PosOrder> query = new LambdaQueryWrapper<>();
+            query.nested(w -> w.eq(PosOrder::getActivity, id).or().eq(PosOrder::getMdActivity, id));
+            boolean exist = posOrderMapper.selectCount(query) > 0;
+            if (exist) {
+                result.setEdit(!exist);
+            } else {
+                result.setEdit(true);
+            }
+        }
+        return success(result);
+    }
+
+    /**
+     * 新增促销活动
+     */
+    @Anonymous
+    @Auth
+    @PostMapping
+    public AjaxResult add(@RequestHeader String token ,@RequestBody SalesPromotion salesPromotion)
+    {
+//        JwtUtil jwtUtil = new JwtUtil();
+//        String id = jwtUtil.getusid(token);
+//        salesPromotion.setShId(Long.valueOf(id));
+        salesPromotion.setType("1");
+        return toAjax(salesPromotionService.insertSalesPromotion(salesPromotion));
+    }
+
+    /**
+     * 修改促销活动
+     */
+    @Anonymous
+    @Auth
+    @PutMapping
+    public AjaxResult edit(@RequestBody SalesPromotion salesPromotion)
+    {
+        return toAjax(salesPromotionService.updateSalesPromotion(salesPromotion));
+    }
+
+    /**
+     * 删除促销活动
+     */
+
+    @Anonymous
+    @Auth
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(salesPromotionService.deleteSalesPromotionByIds(ids));
+    }
+}

+ 218 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/ShindexController.java

@@ -0,0 +1,218 @@
+package com.ruoyi.app.mendian;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.mendian.dto.ExportInput;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.mapper.PosStoreMapper;
+import com.ruoyi.system.mapper.UserBillingMapper;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+@RestController
+@RequestMapping("/index")
+public class ShindexController extends BaseController {
+    @Autowired  //商品分类
+    private IPosFenleiService posFenleiService;
+    @Autowired  //商品
+    private IPosFoodService posFoodService;
+    @Autowired  //门店
+    private IPosStoreService posStoreService;
+    @Autowired  //门店
+    private PosStoreMapper posStoreMapper;
+    @Autowired  //订单
+    private PosOrderMapper posOrderMapper;
+    @Autowired  //账单
+    private UserBillingMapper userBillingMapper;
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IInfoAddressService infoAddressService;
+
+    @Anonymous
+    @GetMapping("/getshindex")
+    public AjaxResult getshindex(@RequestParam String id)
+    {
+        JSONObject org = new JSONObject();
+        int mdsum = posStoreMapper.getshstore(Long.valueOf(id));
+        int dayorder = posOrderMapper.getshoredr(Long.valueOf(id));
+        int qbuorder = posOrderMapper.getshqbuord(Long.valueOf(id));
+        int qbshour = userBillingMapper.getshqbsum(Long.valueOf(id));
+        int qbtixian = userBillingMapper.getshtxsum(Long.valueOf(id));
+        int dtshour = userBillingMapper.getshdtsum(Long.valueOf(id));
+        org.put("stroe",mdsum);
+        org.put("dtorder",dayorder);
+        org.put("qborder",qbuorder);
+        org.put("qbshour",qbshour);
+        org.put("dtshour",dtshour);
+        org.put("ketixian",qbshour-qbtixian);
+        return success(org);
+    }
+
+    //查询商家的订单
+    @Anonymous
+    @Auth
+    @GetMapping("/getstoreorderlist")
+    public AjaxResult getstoreorderlist(@RequestHeader String token,
+                                        @RequestParam Integer page,
+                                        @RequestParam Integer size,
+                                        @RequestParam String mdId,
+                                        @RequestParam(defaultValue = "") String state,
+                                        @RequestParam(defaultValue = "") String diningStatus,
+                                        @RequestParam(defaultValue = "") String startTime,
+                                        @RequestParam(defaultValue = "") String endTime)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosOrder> palist = new Page<>(page,size);
+        QueryWrapper<PosOrder> queryWrapper= new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("cretim");
+        queryWrapper.eq("sh_id",id);
+        System.out.println("商户id:"+id);
+        queryWrapper.eq("md_id",mdId);
+        if(!"".equals(state)){
+            if(state.equals("z01")){
+                queryWrapper.eq("state",0).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("collect_payment","1")
+                ).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("type",1)
+                ).or().eq("state",1).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("sh_id",id)
+                ).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("md_id",mdId)
+                );
+            }else if(state.equals("z234")){
+                queryWrapper.in("state",2,3,4);
+            }else if(state.equals("z23")){
+                queryWrapper.in("state",2,3);
+            }else if(state.equals("z34")){
+                queryWrapper.in("state",3,4);
+            }else if(state.equals("z6789")){
+                queryWrapper.in("state",6,7,8,9);
+            }else{
+                queryWrapper.eq("state",state);
+            }
+        }
+        if(!"".equals(diningStatus)){
+            queryWrapper.eq("dining_status",diningStatus);
+        }
+        if(!"".equals(startTime)){
+            queryWrapper.ge("cretim",startTime);
+        }
+        if(!"".equals(endTime)){
+            queryWrapper.le("cretim",endTime);
+        }
+        IPage<PosOrder> list =  posOrderService.page(palist,queryWrapper);
+        List<PosOrder> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        JSONObject jec = new JSONObject();
+        for(int i=0;i<orlist.size();i++){
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id",orlist.get(i).getId());
+            org.put("ddId",orlist.get(i).getDdId());
+            org.put("shanghu",infoUserService.getById(orlist.get(i).getShId()));
+            org.put("qishou",infoUserService.getById(orlist.get(i).getQsId()));
+            org.put("store",posStoreService.getById(orlist.get(i).getMdId()));
+            org.put("cretim",sdf.format(orlist.get(i).getCretim()));
+            org.put("shaddress",infoAddressService.getById(orlist.get(i).getShdzId()));
+            org.put("user",infoUserService.getById(orlist.get(i).getUserId()));
+            org.put("amount",orlist.get(i).getAmount());
+            org.put("remarks",orlist.get(i).getRemarks());
+            org.put("state",orlist.get(i).getState());
+            org.put("type",orlist.get(i).getType());
+            org.put("jvli",orlist.get(i).getJvli());
+            org.put("freight",orlist.get(i).getFreight());
+            org.put("delryTime",orlist.get(i).getDelryTime());
+            org.put("diningStatus",orlist.get(i).getDiningStatus());
+            org.put("collectPayment",orlist.get(i).getCollectPayment());
+            org.put("food",JSONArray.parseArray(orlist.get(i).getFood()));
+            org.put("activity",orlist.get(i).getActivity());
+            org.put("mdActivity",orlist.get(i).getMdActivity());
+            org.put("salesReduction",orlist.get(i).getSalesReduction());
+            org.put("mdSalesReduction",orlist.get(i).getMdSalesReduction());
+            org.put("salesName",orlist.get(i).getSalesName());
+            org.put("mdSalesName",orlist.get(i).getMdSalesName());
+            org.put("mdDiscountAmount",orlist.get(i).getMdDiscountAmount());
+            org.put("discountAmount",orlist.get(i).getDiscountAmount());
+            org.put("mdYhId",orlist.get(i).getMdYhId());
+            org.put("mdYhName",orlist.get(i).getMdYhName());
+            org.put("yhId",orlist.get(i).getYhId());
+            org.put("yhName",orlist.get(i).getYhName());
+            org.put("points",orlist.get(i).getPoints());
+            org.put("pointsReduction",orlist.get(i).getPointsReduction());
+            arr.add(org);
+        }
+        jec.put("page",list.getPages());
+        jec.put("size",list.getSize());
+        jec.put("total",list.getTotal());
+        jec.put("list",arr);
+        return success(jec);
+    }
+    @Anonymous
+    @Auth
+    @PostMapping("/export")
+    public void export(HttpServletResponse response,@RequestHeader String token, @RequestBody ExportInput input){
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<PosOrder> queryWrapper= new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("cretim");
+        queryWrapper.eq("sh_id",id);
+        System.out.println("商户id:"+id);
+        queryWrapper.eq("md_id",input.getMdId());
+        if(!"".equals(input.getState())){
+            if(input.getState().equals("z01")){
+                queryWrapper.eq("state",0).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("collect_payment","1")
+                ).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("type",1)
+                ).or().eq("state",1).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("sh_id",id)
+                ).and(
+                        posOrderQueryWrapper -> posOrderQueryWrapper.eq("md_id",input.getMdId())
+                );
+            }else if(input.getState().equals("z234")){
+                queryWrapper.in("state",2,3,4);
+            }else if(input.getState().equals("z23")){
+                queryWrapper.in("state",2,3);
+            }else if(input.getState().equals("z34")){
+                queryWrapper.in("state",3,4);
+            }else if(input.getState().equals("z6789")){
+                queryWrapper.in("state",6,7,8,9);
+            }else{
+                queryWrapper.eq("state",input.getState());
+            }
+        }
+        if(!"".equals(input.getDiningStatus())){
+            queryWrapper.eq("dining_status",input.getDiningStatus());
+        }
+        if(!"".equals(input.getStartTime())){
+            queryWrapper.ge("cretim",input.getStartTime());
+        }
+        if(!"".equals(input.getEndTime())){
+            queryWrapper.le("cretim",input.getEndTime());
+        }
+        List<PosOrder> list =  posOrderService.list(queryWrapper);
+        ExcelUtil<PosOrder> util = new ExcelUtil<PosOrder>(PosOrder.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.posorder"));
+    }
+
+}

+ 14 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/dto/ExportInput.java

@@ -0,0 +1,14 @@
+package com.ruoyi.app.mendian.dto;
+
+import lombok.Data;
+
+@Data
+public class ExportInput {
+    private Integer page;
+    private Integer size;
+    private String mdId;
+    private String state = "";
+    private String diningStatus = "";
+    private String startTime = "";
+    private String endTime = "";
+}

+ 105 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/DistanceMultiplierController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.app.order;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.DistanceMultiplier;
+import com.ruoyi.system.service.IDistanceMultiplierService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * DistanceMultiplierController
+ * 
+ * @author ruoyi
+ * @date 2024-08-23
+ */
+@RestController
+@RequestMapping("/system/multiplier")
+public class DistanceMultiplierController extends BaseController
+{
+    @Autowired
+    private IDistanceMultiplierService distanceMultiplierService;
+
+    /**
+     * 查询DistanceMultiplier列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:multiplier:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(DistanceMultiplier distanceMultiplier)
+    {
+        startPage();
+        List<DistanceMultiplier> list = distanceMultiplierService.selectDistanceMultiplierList(distanceMultiplier);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出DistanceMultiplier列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:multiplier:export')")
+    @Log(title = "DistanceMultiplier", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, DistanceMultiplier distanceMultiplier)
+    {
+        List<DistanceMultiplier> list = distanceMultiplierService.selectDistanceMultiplierList(distanceMultiplier);
+        ExcelUtil<DistanceMultiplier> util = new ExcelUtil<DistanceMultiplier>(DistanceMultiplier.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.distancemultiplier"));
+    }
+
+    /**
+     * 获取DistanceMultiplier详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:multiplier:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(distanceMultiplierService.selectDistanceMultiplierById(id));
+    }
+
+    /**
+     * 新增DistanceMultiplier
+     */
+    @PreAuthorize("@ss.hasPermi('system:multiplier:add')")
+    @Log(title = "DistanceMultiplier", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody DistanceMultiplier distanceMultiplier)
+    {
+        return toAjax(distanceMultiplierService.insertDistanceMultiplier(distanceMultiplier));
+    }
+
+    /**
+     * 修改DistanceMultiplier
+     */
+    @PreAuthorize("@ss.hasPermi('system:multiplier:edit')")
+    @Log(title = "DistanceMultiplier", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody DistanceMultiplier distanceMultiplier)
+    {
+        return toAjax(distanceMultiplierService.updateDistanceMultiplier(distanceMultiplier));
+    }
+
+    /**
+     * 删除DistanceMultiplier
+     */
+    @PreAuthorize("@ss.hasPermi('system:multiplier:remove')")
+    @Log(title = "DistanceMultiplier", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(distanceMultiplierService.deleteDistanceMultiplierByIds(ids));
+    }
+}

+ 172 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/InfoAddressController.java

@@ -0,0 +1,172 @@
+package com.ruoyi.app.order;
+
+import java.math.BigDecimal;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.mapper.InfoAddressMapper;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.InfoAddress;
+import com.ruoyi.system.service.IInfoAddressService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * addressController
+ * 
+ * @author ruoyi
+ * @date 2023-05-24
+ */
+@RestController
+@RequestMapping("/system/address")
+public class InfoAddressController extends BaseController
+{
+    @Autowired
+    private IInfoAddressService infoAddressService;
+    @Autowired
+    private InfoAddressMapper infoAddressMapper;
+
+
+    //删除收货地址
+    @Anonymous
+    @GetMapping("/deleaddress")
+    public AjaxResult deleaddress(@RequestParam Long id)
+    {
+        return toAjax(infoAddressService.deleteById(id));
+    }
+
+    //获取用户收货地址详请
+    @Anonymous
+    @GetMapping("/getaddressxq")
+    public AjaxResult getaddressxq(@RequestParam Long id)
+    {
+        InfoAddress address = infoAddressService.getById(id);
+        return success(MessageUtils.message("no.obtained.success"), address);
+    }
+    //根据距离获取我的地址
+    @Anonymous
+    @Auth
+    @GetMapping("/getzuijinaddress")
+    public AjaxResult getzuijinaddress(@RequestHeader String token,
+                                       @RequestParam BigDecimal longitude,
+                                       @RequestParam BigDecimal latitude)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        List<InfoAddress> list = infoAddressMapper.getmyaddress(longitude,latitude, Integer.valueOf(id));
+        return success(MessageUtils.message("no.obtained.success"), list);
+    }
+    //获取用户收货地址信息
+    @Anonymous
+    @Auth
+    @GetMapping("/getaddress")
+    public AjaxResult getaddress(@RequestHeader String token)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<InfoAddress> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",id);
+        List<InfoAddress> list = infoAddressService.list(queryWrapper);
+        return success(MessageUtils.message("no.obtained.success"), list);
+    }
+
+    //添加用户收货地址信息
+    @Anonymous
+    @Auth
+    @PostMapping("/address")
+    public AjaxResult address(@RequestHeader String token,@RequestBody InfoAddress infoAddress)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        infoAddress.setUserId(Long.valueOf(id));
+        boolean org = infoAddressService.saveOrUpdate(infoAddress);
+        if(org){
+            return success();
+        }else {
+            return error();
+        }
+
+    }
+
+
+    /**
+     * 查询address列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:address:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(InfoAddress infoAddress)
+    {
+        startPage();
+        List<InfoAddress> list = infoAddressService.selectInfoAddressList(infoAddress);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出address列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:address:export')")
+    @Log(title = "address", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, InfoAddress infoAddress)
+    {
+        List<InfoAddress> list = infoAddressService.selectInfoAddressList(infoAddress);
+        ExcelUtil<InfoAddress> util = new ExcelUtil<InfoAddress>(InfoAddress.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.address"));
+    }
+
+    /**
+     * 获取address详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:address:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(infoAddressService.selectInfoAddressById(id));
+    }
+
+    /**
+     * 新增address
+     */
+    @PreAuthorize("@ss.hasPermi('system:address:add')")
+    @Log(title = "address", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody InfoAddress infoAddress)
+    {
+        return toAjax(infoAddressService.insertInfoAddress(infoAddress));
+    }
+
+    /**
+     * 修改address
+     */
+    @PreAuthorize("@ss.hasPermi('system:address:edit')")
+    @Log(title = "address", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody InfoAddress infoAddress)
+    {
+        return toAjax(infoAddressService.updateInfoAddress(infoAddress));
+    }
+
+    /**
+     * 删除address
+     */
+    @PreAuthorize("@ss.hasPermi('system:address:remove')")
+    @Log(title = "address", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(infoAddressService.deleteInfoAddressByIds(ids));
+    }
+}

+ 45 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PointController.java

@@ -0,0 +1,45 @@
+package com.ruoyi.app.order;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.domain.PointsTransaction;
+import com.ruoyi.system.service.IPointsTransactionService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 用户积分Controller
+ *
+ * @author ruoyi
+ * @date 2023-05-23
+ */
+@RestController
+@RequestMapping("/system/points")
+public class PointController extends BaseController {
+    @Autowired
+    private IPointsTransactionService  pointsTransactionService;
+    /**
+     * 用户积分流水分页列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getpoints")
+    public AjaxResult getpoints(@RequestHeader String token,
+                                @RequestParam Long page,
+                                @RequestParam Long size) {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        IPage<PointsTransaction> pg=new Page<>(page,size);
+        LambdaQueryWrapper<PointsTransaction> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PointsTransaction::getUserId, id);
+       queryWrapper.orderByDesc(PointsTransaction::getCreateTime);
+        IPage<PointsTransaction> data = pointsTransactionService.page(pg, queryWrapper);
+        return success(data);
+    }
+}

+ 48 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PointController.java~

@@ -0,0 +1,48 @@
+package com.ruoyi.app.order;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.domain.PointsTransaction;
+import com.ruoyi.system.service.IPointsTransactionService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 用户积分Controller
+ *
+ * @author ruoyi
+ * @date 2023-05-23
+ */
+@RestController
+@RequestMapping("/system/points")
+public class PointController extends BaseController {
+    @Autowired
+    private IPointsTransactionService  pointsTransactionService;
+    /**
+     * 用户积分流水分页列表
+     */
+    @Anonymous
+    @Auth
+    @RequestMapping("/getpoints")
+    public AjaxResult getpoints(@RequestHeader String token,
+                                @RequestParam Long page,
+                                @RequestParam Long size) {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        IPage<PointsTransaction> pg=new Page<>(page,size);
+        LambdaQueryWrapper<PointsTransaction> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PointsTransaction::getUserId, id);
+       queryWrapper.orderByDesc(PointsTransaction::getCreateTime);
+        IPage<PointsTransaction> data = pointsTransactionService.page(pg, queryWrapper);
+        return success(data);
+    }
+}

+ 105 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosFreightController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.app.order;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.PosFreight;
+import com.ruoyi.system.service.IPosFreightService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * freightController
+ * 
+ * @author ruoyi
+ * @date 2023-07-15
+ */
+@RestController
+@RequestMapping("/system/freight")
+public class PosFreightController extends BaseController
+{
+    @Autowired
+    private IPosFreightService posFreightService;
+
+    /**
+     * 查询freight列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:freight:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosFreight posFreight)
+    {
+        startPage();
+        List<PosFreight> list = posFreightService.selectPosFreightList(posFreight);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出freight列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:freight:export')")
+    @Log(title = "freight", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosFreight posFreight)
+    {
+        List<PosFreight> list = posFreightService.selectPosFreightList(posFreight);
+        ExcelUtil<PosFreight> util = new ExcelUtil<PosFreight>(PosFreight.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.freight"));
+    }
+
+    /**
+     * 获取freight详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:freight:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posFreightService.selectPosFreightById(id));
+    }
+
+    /**
+     * 新增freight
+     */
+    @PreAuthorize("@ss.hasPermi('system:freight:add')")
+    @Log(title = "freight", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosFreight posFreight)
+    {
+        return toAjax(posFreightService.insertPosFreight(posFreight));
+    }
+
+    /**
+     * 修改freight
+     */
+    @PreAuthorize("@ss.hasPermi('system:freight:edit')")
+    @Log(title = "freight", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosFreight posFreight)
+    {
+        return toAjax(posFreightService.updatePosFreight(posFreight));
+    }
+
+    /**
+     * 删除freight
+     */
+    @PreAuthorize("@ss.hasPermi('system:freight:remove')")
+    @Log(title = "freight", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posFreightService.deletePosFreightByIds(ids));
+    }
+}

+ 1684 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java

@@ -0,0 +1,1684 @@
+package com.ruoyi.app.order;
+
+import cn.hutool.core.lang.func.Func;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.ruoyi.app.order.dto.OrderPositionInfo;
+import com.ruoyi.app.order.dto.OrderPushBodyDto;
+import com.ruoyi.app.order.dto.PositionDto;
+import com.ruoyi.app.order.dto.QsDto;
+import com.ruoyi.app.pay.PayController;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.PayPush;
+import com.ruoyi.app.utils.event.PushEvent;
+import com.ruoyi.app.utils.event.PushEventService;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.domain.vo.OrderDTO;
+import com.ruoyi.system.domain.vo.PayVN;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.mapper.RiderPositionMapper;
+import com.ruoyi.system.mapper.UserBillingMapper;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.GetArea;
+import com.ruoyi.system.utils.JwtUtil;
+import lombok.SneakyThrows;
+import org.checkerframework.checker.units.qual.A;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * posorderController
+ *
+ * @author ruoyi
+ * @date 2023-05-23
+ */
+@RestController
+@RequestMapping("/system/order")
+public class PosOrderController extends BaseController {
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IPosStoreService posStoreService;
+    @Autowired
+    private IInfoAddressService infoAddressService;
+    @Autowired
+    private IUserFootprintService userFootprintService;
+    @Autowired
+    private PosOrderMapper posOrderMapper;
+    @Autowired
+    private IRiderPositionService riderPositionService;
+    @Autowired
+    private IUserBillingService userBillingService;
+    @Autowired
+    private UserBillingMapper userBillingMapper;
+    @Autowired
+    private IPosMarginService posMarginService;
+    @Autowired
+    private ISalesPromotionService salesPromotionService;
+    @Autowired
+    private IPosAppealService posAppealService;
+    @Autowired  //商品
+    private IPosFoodService posFoodService;
+    @Autowired  //经营时间
+    private IOperatingHoursService operatingHoursService;
+    @Autowired
+    private IVipUserQuanyiService userQuanyiService;
+    @Autowired
+    private ISysPointControlService pointControlService;
+    @Autowired
+    private IUserWalletService userWalletService;
+    @Autowired
+    private RiderPositionMapper riderPositionMapper;
+    @Autowired
+    private IPointsTransactionService pointsTransactionService;
+    @Autowired
+    private PayController payController;
+    @Autowired
+    private PushEventService pushEventService;
+    @Autowired
+    private IPosOrderRatingService posOrderRatingService;
+    @Autowired
+    private IFoodStatisticsService foodStatisticsService;
+
+
+    //查询用户足迹
+    @Anonymous
+    @Auth
+    @GetMapping("/getuserfootlist")
+    public AjaxResult getuserfootlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<UserFootprint> palist = new Page<>(page, size);
+        QueryWrapper<UserFootprint> queryWrapper = new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("cretim");
+        queryWrapper.eq("user_id", id);
+        IPage<UserFootprint> list = userFootprintService.page(palist, queryWrapper);
+        List<UserFootprint> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        for (int i = 0; i < orlist.size(); i++) {
+            JSONObject org = new JSONObject();
+            org.put("id", orlist.get(i).getId());
+            org.put("user", infoUserService.selectInfoUserByUserId(orlist.get(i).getUserId()));
+            org.put("store", posStoreService.getById(orlist.get(i).getMdId()));
+            org.put("cretim", sdf.format(orlist.get(i).getId()));
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+
+
+    //修改订单
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PostMapping("/setorderuzt")
+    public AjaxResult setorderuzt(@RequestHeader String token, @RequestBody PosOrder posOrder) {
+        JwtUtil jwtUtil = new JwtUtil();
+        PayPush push = new PayPush();
+        String id = jwtUtil.getusid(token);
+        if (posOrder.getState() != null) {
+            //状态为送达,设置送达时间
+            if (posOrder.getState() == 12) {
+                posOrder.setSdTime(new Date());
+            }
+            System.out.println("修改订单状态信息:" + JSON.toJSONString(posOrder));
+            //设置支付类型为货到付款
+            if (posOrder.getState() == 0 && "1".equals(posOrder.getCollectPayment())) {
+                System.out.println("进入设置paytype等于1");
+                posOrder.setPayType("1");
+            }
+            //取餐时设置预计送达时间
+            setYjsdTime(posOrder);
+            if (posOrder.getState() == 5) {
+                return setOrderState5(posOrder);
+            } else if (posOrder.getState() == 2) {
+                return setOrderState2(posOrder, id);
+            } else if (posOrder.getState() == 3 || posOrder.getState() == 4 || posOrder.getState() == 12)
+            {
+                return setOrderQsState(posOrder, id, push);
+            } else if (posOrder.getState() == 7) {
+                return setOrderState7(posOrder);
+            } else {
+
+                boolean org = posOrderService.saveOrUpdate(posOrder);
+                PosOrder order = posOrderService.getById(posOrder.getId());
+                if (order.getState() == 0 && order.getCollectPayment().equals("1")) {
+                    sendHdfkMessage(order, push);
+                }
+                //作废退回积分
+                if (posOrder.getState() == 10 && order.getPoints() != null && order.getPoints() > 0) {
+                    returnPoints(order.getUserId(), order.getDdId(), Long.valueOf(order.getPoints()));
+                }
+                if (org) {
+                    return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+                } else {
+                    return error();
+                }
+            }
+        } else {
+            return setOrderNoState(posOrder, id);
+        }
+    }
+
+    //骑手接单、取餐、送达
+    private AjaxResult setOrderQsState(PosOrder posOrder, String id, PayPush push) {
+        PosOrder orst = posOrderService.getById(posOrder.getId());
+        if (orst.getState() == 3 && posOrder.getState() == 3) {
+            return error(MessageUtils.message("no.order.snatched"));
+        } else {
+            if(posOrder.getState()==3){
+                QueryWrapper<PosOrder> wrapper = new QueryWrapper<>();
+                wrapper.eq("qs_id", id);
+                wrapper.in("state", 3, 4);
+                List<PosOrder> orsts = posOrderService.list(wrapper);
+                if (orsts.size() > 0) {
+                    return error(MessageUtils.message("no.exist.undelivered.order"));
+                }
+            }
+            String userMessage= MessageUtils.message("no.message.push.delivery.personnel.receiving.order");
+            if(posOrder.getState()==4){
+                userMessage= MessageUtils.message("no.message.push.delivery.personnel.qspsz.order");
+            }else if(posOrder.getState()==12){
+                userMessage= MessageUtils.message("no.message.push.delivery.personnel.qsysd.order");
+            }
+            int zsou = userBillingMapper.gettypesum(Long.valueOf(id), 1L);
+            int zcz = userBillingMapper.gettypesum(Long.valueOf(id), 2L);
+            int xiaf = userBillingMapper.gettypesum(Long.valueOf(id), 3L);
+            int yure = zsou - zcz - xiaf;
+            PosMargin posMargin = posMarginService.getById(2);
+            System.out.println("用户余额:" + yure);
+            System.out.println("保证金:" + posMargin.getAmount());
+            //临时代码开始
+            if (orst.getCollectPayment().equals("1")) {
+                System.out.println("结果:" + orst.getAmount());
+                boolean org = posOrderService.saveOrUpdate(posOrder);
+                if (org) {
+                    if(posOrder.getState()==3) {
+                        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
+                        queryWrapper.eq("dd_id", orst.getDdId());
+                        queryWrapper.eq("type", "3");
+                        queryWrapper.eq("state", "3");
+                        UserBilling foot = userBillingService.getOne(queryWrapper);
+                        foot.setState("0");
+                        foot.setIllustrate("Rider Payment Order");
+                        foot.setBalancePay("1");
+                        foot.setPaymentId(String.valueOf(id));
+                        userBillingService.saveOrUpdate(foot);
+                    }
+                    InfoUser user = infoUserService.getById(orst.getUserId());
+                    InfoUser shu = infoUserService.getById(orst.getShId());
+                    if (!"".equals(user.getCid())) {
+                        logger.info("用户cid:" + user.getCid() + "推送");
+                        push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), userMessage, OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState())));
+                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), userMessage, OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState())));
+                    }
+                    if (!"".equals(shu.getCid()) && posOrder.getState()==3) {
+                        logger.info("商家cid:" + user.getCid() + "推送");
+                        push.shpush(shu.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState())));
+                        pushEventService.PublisherEvent(shu.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState())));
+                    }
+                    return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+                } else {
+                    return error();
+                }
+
+            } else {
+                boolean org = posOrderService.saveOrUpdate(posOrder);
+                if (org) {
+                    InfoUser user = infoUserService.getById(orst.getUserId());
+                    if (!"".equals(user.getCid())) {
+                        logger.info("用户cid:" + user.getCid() + "推送");
+                        push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), userMessage, OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState())));
+                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), userMessage, OrderPushBodyDto.getJson(String.valueOf(orst.getDdId()), String.valueOf(posOrder.getState())));
+                    }
+                    return success(MessageUtils.message("no.modify.success"), orst.getId());
+                } else {
+                    return error();
+                }
+            }
+        }
+    }
+
+    //商家接单
+    private AjaxResult setOrderState2(PosOrder posOrder,String id) {
+        int zsou = userBillingMapper.gettypesum(Long.valueOf(id), 1L);
+        int zcz = userBillingMapper.gettypesum(Long.valueOf(id), 2L);
+        int xiaof = userBillingMapper.gettypesum(Long.valueOf(id), 3L);
+        int yure = zsou - zcz - xiaof;
+        PosMargin posMargin = posMarginService.getById(1);
+        InfoUser user = infoUserService.getById(id);
+        if (user.getUserType().equals("1")) {
+            boolean org = posOrderService.saveOrUpdate(posOrder);
+            if (org) {
+                PosOrder order = posOrderService.getById(posOrder.getId());
+                return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+            } else {
+                return error();
+            }
+        } else {
+            if (yure <= (int) Math.round(posMargin.getAmount())) {
+                return error(MessageUtils.message("no.insufficient.user.security.deposit"));
+            } else {
+                boolean org = posOrderService.saveOrUpdate(posOrder);
+                if (org) {
+                    PosOrder order = posOrderService.getById(posOrder.getId());
+                    return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+                } else {
+                    return error();
+                }
+            }
+        }
+    }
+    //订单完成
+    private AjaxResult setOrderState5(PosOrder posOrder){
+        boolean org = posOrderService.saveOrUpdate(posOrder);
+        if (org) {
+            PosOrder order = posOrderService.getById(posOrder.getId());
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            wrapper.eq("dd_id", order.getId());
+
+            UserBilling billing = userBillingService.getOne(wrapper);
+            if (billing == null) {
+                setSanghuBilling(order);
+                setQishouBilling(order);
+            }
+            return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+        } else {
+            return error();
+        }
+    }
+
+    //同意退款
+    private AjaxResult setOrderState7(PosOrder posOrder) {
+        boolean org = posOrderService.saveOrUpdate(posOrder);
+        PosOrder order = posOrderService.getById(posOrder.getId());
+        if (order.getPoints() != null && order.getPoints() > 0) {
+            returnPoints(order.getUserId(), order.getDdId(), Long.valueOf(order.getPoints()));
+        }
+        if (org) {
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            wrapper.eq("dd_id", posOrder.getId());
+            List<UserBilling> billing = userBillingService.list(wrapper);
+            if (billing.size() == 0) {
+                return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+            } else {
+                for (int i = 0; i < billing.size(); i++) {
+                    UserBilling user = new UserBilling();
+                    user.setId(billing.get(i).getId());
+                    user.setState("1");
+                    userBillingService.saveOrUpdate(user);
+                }
+                return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+            }
+        } else {
+            return error();
+        }
+    }
+
+    //更改订单没传订单状态
+    private AjaxResult setOrderNoState(PosOrder posOrder, String id) {
+        PosOrder ordera = posOrderService.getById(posOrder.getId());
+        //订单金额限制100万改为200万
+        if (posOrder.getCollectPayment().equals("1") && ordera.getAmount() > 2000000) {
+            return error(MessageUtils.message("no.cash_on_delivery_amount.exceed.limit_amount"));
+        }
+        QueryWrapper<PosOrder> query = new QueryWrapper<>();
+        query.eq("user_id", id);
+        query.eq("collect_payment", "1");
+        query.notIn("state", 5, 10, 11);
+        List<PosOrder> posOrders = posOrderService.list(query);
+        //到付能存在2单未完成,第3单弹出提示;修改做判断的前提是当前订单不是为到付
+        if (posOrders.size() >= 2 && posOrder.getCollectPayment().equals("1") && !"1".equals(ordera.getCollectPayment())) {
+            return error(MessageUtils.message("no.exist.cash_on_delivery_order.incomplete"));
+        }
+        boolean org = posOrderService.saveOrUpdate(posOrder);
+        if (org) {
+            PosOrder order = posOrderService.getById(posOrder.getId());
+
+            return success(MessageUtils.message("no.modify.success"), posOrder.getId());
+        } else {
+            return error();
+        }
+    }
+
+    /**
+     * 获取预计送达时间
+     *
+     * @param posOrder
+     * @return
+     */
+    private String setYjsdTime(PosOrder posOrder) {
+        try {
+            if (posOrder.getState() == 4) {
+                GetArea getArea = new GetArea();
+                PosOrder order = posOrderService.getById(posOrder.getId());
+                String mdlat = order.getLongitude() + "," + order.getLatitude();
+                InfoAddress shDz = infoAddressService.getById(order.getShdzId());
+
+                String shlat = shDz.getLongitude() + "," + shDz.getLatitude();
+                double time = getArea.getMotorbikeDuration(mdlat, shlat);
+                DateUtil dateUtil = new DateUtil();
+                String start = dateUtil.getHourAndMinute((long) time);
+                double endTime = time + 600; //加上10分钟
+                String end = dateUtil.getHourAndMinute((long) endTime);
+                posOrder.setYjsdTime(start + "-" + end);
+                return start + "-" + end;
+            }
+            return "";
+        } catch (Exception e) {
+            logger.error("获取预计送达时间异常,id:" + posOrder.getId() + "异常信息:", e);
+            return "";
+        }
+    }
+
+    //修改订单
+    @Anonymous
+    @PostMapping("/testYjsdTime")
+    public String testYjsdTime(@RequestBody PosOrder order) {
+        return setYjsdTime(order);
+
+    }
+
+
+    //执行商户分成
+    public void setSanghuBilling(@NotNull PosOrder posOrder) {
+        UserBilling billing = new UserBilling();
+        DecimalFormat df = new DecimalFormat("#.00");
+        InfoUser user = infoUserService.getById(posOrder.getShId());
+        Double fcbili = user.getCommission() == null ? 0.00 : user.getCommission();
+        JSONArray list = JSONArray.parseArray(posOrder.getFood());
+        int fenc = 0;
+        for (int i = 0; i < list.size(); i++) {
+            JSONObject foods = list.getJSONObject(i);
+            //20250612修改,商品金额等于价格乘以数量;未修改前金额直接为商品价格
+            int price = foods.getInteger("price");
+            int otherPrice = foods.getInteger("otherPrice"); //规格价格
+            int num = foods.getInteger("number");
+            int age = (price + otherPrice) * num; //价格=商品价格+规格价格
+            fenc += age;
+        }
+//        Double fenc = posOrder.getAmount()-posOrder.getFreight();
+
+        //商家分成总金额,减去商家优惠金额,减去商家活动金额(type=2 为平台指定商家优惠券,由平台承担)
+        if (posOrder.getMdYhId() != null && posOrder.getMdDiscountAmount() != null) {
+            VipUserQuanyi userQuanyi = userQuanyiService.getById(posOrder.getMdYhId());
+            if (userQuanyi != null && "1".equals(userQuanyi.getType())) {
+                fenc = fenc - posOrder.getMdDiscountAmount();
+            }
+
+        }
+        if (posOrder.getMdActivity() != null && posOrder.getMdSalesReduction() != null) {
+            fenc = fenc - posOrder.getMdSalesReduction();
+        }
+
+        Double chouc = fenc * fcbili;
+        Double shfc = fenc - chouc;
+        billing.setUserId(posOrder.getShId());
+        billing.setDdId(String.valueOf(posOrder.getDdId()));
+        billing.setType("0");
+        billing.setAmount(Double.valueOf(df.format(shfc)));
+        billing.setDivvy(Double.valueOf(df.format(chouc)));
+        billing.setState("0");
+        billing.setMdId(posOrder.getMdId());
+        int reg = userBillingService.insertUserBilling(billing);
+        if (reg == 1) {
+            System.out.println("商户分成成功,订单号:" + posOrder.getDdId() + ",分成金额:" + shfc + ",抽成:" + chouc);
+
+        } else {
+            System.out.println("订单:" + posOrder.getDdId() + "分成失败");
+        }
+    }
+
+    //执行骑手分成
+    public void setQishouBilling(@NotNull PosOrder posOrder) {
+        UserBilling billing = new UserBilling();
+        DecimalFormat df = new DecimalFormat("#.00");
+        InfoUser user = infoUserService.getById(posOrder.getQsId());
+        if (user == null) {
+            System.out.println("订单无骑手");
+        } else {
+            Double fcbili = user.getCommission() == null ? 0.00 : user.getCommission();
+            Double fenc = posOrder.getFreight();
+            Double chouc = fenc * fcbili;
+            Double shfc = fenc - chouc;
+            billing.setUserId(posOrder.getQsId());
+            billing.setDdId(String.valueOf(posOrder.getDdId()));
+            billing.setType("0");
+            billing.setAmount(Double.valueOf(df.format(shfc)));
+            billing.setDivvy(Double.valueOf(df.format(chouc)));
+            billing.setState("0");
+            billing.setMdId(posOrder.getMdId());
+            int reg = userBillingService.insertUserBilling(billing);
+            if (reg == 1) {
+                System.out.println("骑手分成成功,订单号:" + posOrder.getDdId() + ",分成金额:" + shfc + ",抽成:" + chouc);
+            } else {
+                System.out.println("订单:" + posOrder.getDdId() + "分成失败");
+            }
+        }
+
+    }
+
+    //后台查询详情
+    @GetMapping("/getorderhout")
+    public AjaxResult getorderhout(@RequestParam String id) {
+        PosOrder orlist = posOrderService.getById(id);
+        JSONObject org = new JSONObject();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        org.put("id", orlist.getId());
+        org.put("ddId", orlist.getDdId());
+        org.put("shanghu", infoUserService.getById(orlist.getShId()));
+        org.put("store", posStoreService.getById(orlist.getMdId()));
+        org.put("cretim", sdf.format(orlist.getCretim()));
+        org.put("shdzId", orlist.getShdzId());
+        org.put("shaddress", orlist.getShAddress() == null ? infoAddressService.getById(orlist.getShdzId()) : JSONObject.parseObject(orlist.getShAddress()));
+        org.put("user", infoUserService.getById(orlist.getUserId()));
+        org.put("amount", orlist.getAmount());
+        org.put("kefuState", orlist.getKefuState());
+        org.put("kefuContent", orlist.getKefuContent());
+        org.put("kefuRepeat", orlist.getKefuRepeat());
+        org.put("repeatDdId", orlist.getRepeatDdId());
+        org.put("remarks", orlist.getRemarks());
+        org.put("state", orlist.getState());
+        org.put("type", orlist.getType());
+        org.put("jvli", orlist.getJvli());
+        org.put("freight", orlist.getFreight());
+        org.put("delryTime", orlist.getDelryTime());
+        org.put("longitude", orlist.getLongitude());
+        org.put("latitude", orlist.getLatitude());
+        org.put("qsuser", infoUserService.getById(orlist.getQsId()));
+        org.put("payUrl", orlist.getPayUrl());
+        QueryWrapper<RiderPosition> query = new QueryWrapper<>();
+        query.eq("rider_id", orlist.getQsId());
+        org.put("RiderPosition", orlist.getQsId() == null ? null : riderPositionService.getOne(query));
+        org.put("diningStatus", orlist.getDiningStatus());
+        org.put("collectPayment", orlist.getCollectPayment());
+        org.put("food", JSONArray.parseArray(orlist.getFood()));
+//        org.put("activity",salesPromotionService.getById(orlist.getActivity()));
+        org.put("activity", orlist.getActivity());
+        org.put("mdActivity", orlist.getMdActivity());
+        org.put("salesReduction", orlist.getSalesReduction());
+        org.put("mdSalesReduction", orlist.getMdSalesReduction());
+        org.put("salesName", orlist.getSalesName());
+        org.put("mdSalesName", orlist.getMdSalesName());
+        org.put("mdDiscountAmount", orlist.getMdDiscountAmount());
+        org.put("discountAmount", orlist.getDiscountAmount());
+        org.put("mdYhId", orlist.getMdYhId());
+        org.put("mdYhName", orlist.getMdYhName());
+        org.put("yhId", orlist.getYhId());
+        org.put("yhName", orlist.getYhName());
+        org.put("points", orlist.getPoints());
+        org.put("pointsReduction", orlist.getPointsReduction());
+        org.put("sdTime", orlist.getSdTime());
+        org.put("payType", orlist.getPayType());
+        return success(org);
+    }
+
+    /**
+     * 通过订单号查询订单详情
+     *
+     * @param ddid
+     * @return
+     */
+    //查询订单详情
+    @Anonymous
+    @Auth
+    @GetMapping("/getorderxq")
+    public AjaxResult getorderxq(@RequestParam String ddid) {
+        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("dd_id", ddid);
+        PosOrder orlist = posOrderService.getOne(queryWrapper);
+        JSONObject org = new JSONObject();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        org.put("id", orlist.getId());
+        org.put("ddId", orlist.getDdId());
+        org.put("shanghu", infoUserService.getById(orlist.getShId()));
+        org.put("store", posStoreService.getById(orlist.getMdId()));
+        org.put("cretim", sdf.format(orlist.getCretim()));
+        org.put("shdzId", orlist.getShdzId());
+        org.put("shaddress", orlist.getShAddress() == null ? infoAddressService.getById(orlist.getShdzId()) : JSONObject.parseObject(orlist.getShAddress()));
+        org.put("user", infoUserService.getById(orlist.getUserId()));
+        org.put("amount", orlist.getAmount());
+        org.put("kefuState", orlist.getKefuState());
+        org.put("kefuContent", orlist.getKefuContent());
+        org.put("kefuRepeat", orlist.getKefuRepeat());
+        org.put("repeatDdId", orlist.getRepeatDdId());
+        org.put("remarks", orlist.getRemarks());
+        org.put("state", orlist.getState());
+        org.put("type", orlist.getType());
+        org.put("jvli", orlist.getJvli());
+        org.put("freight", orlist.getFreight());
+        org.put("delryTime", orlist.getDelryTime());
+        org.put("longitude", orlist.getLongitude());
+        org.put("latitude", orlist.getLatitude());
+        org.put("qsId", orlist.getQsId());
+        org.put("sqImg", orlist.getQsImg());
+        org.put("discountAmount", orlist.getDiscountAmount());
+        InfoUser qsUser = infoUserService.getById(orlist.getQsId());
+        setQsStar(qsUser);
+        org.put("qsuser", orlist.getQsId() == null ? null : qsUser);
+        org.put("payUrl", orlist.getPayUrl());
+        QueryWrapper<RiderPosition> query = new QueryWrapper<>();
+        query.eq("rider_id", orlist.getQsId());
+        org.put("RiderPosition", orlist.getQsId() == null ? null : riderPositionService.getOne(query));
+        org.put("diningStatus", orlist.getDiningStatus());
+        org.put("collectPayment", orlist.getCollectPayment());
+        org.put("food", JSONArray.parseArray(orlist.getFood()));
+//        org.put("activity",salesPromotionService.getById(orlist.getActivity()));
+
+        org.put("activity", orlist.getActivity());
+        org.put("mdActivity", orlist.getMdActivity());
+        org.put("salesReduction", orlist.getSalesReduction());
+        org.put("mdSalesReduction", orlist.getMdSalesReduction());
+        org.put("salesName", orlist.getSalesName());
+        org.put("mdSalesName", orlist.getMdSalesName());
+        org.put("mdDiscountAmount", orlist.getMdDiscountAmount());
+        org.put("discountAmount", orlist.getDiscountAmount());
+        org.put("mdYhId", orlist.getMdYhId());
+        org.put("mdYhName", orlist.getMdYhName());
+        org.put("yhId", orlist.getYhId());
+        org.put("yhName", orlist.getYhName());
+        org.put("points", orlist.getPoints());
+        org.put("pointsReduction", orlist.getPointsReduction());
+        org.put("sdTime", orlist.getSdTime());
+        org.put("payType", orlist.getPayType());
+        int count = posOrderRatingService.getBaseMapper().selectCount(new QueryWrapper<PosOrderRating>().eq("dd_id", ddid));
+        //是否已经评论
+        org.put("isCommented", count > 0);
+        return success(org);
+    }
+
+    /**
+     * 设置骑手星级
+     *
+     * @param infoUser
+     */
+
+    private void setQsStar(InfoUser infoUser) {
+        if (infoUser != null) {
+            QueryWrapper<PosOrderRating> wrapper = new QueryWrapper<>();
+            wrapper.eq("qs_id", infoUser.getUserId()).isNotNull("qs_stars").isNotNull("qs_stars").select("ROUND(AVG(qs_stars), 1) as qs_stars");
+            List<Map<String, Object>> map = posOrderRatingService.getBaseMapper().selectMaps(wrapper);
+            if (!map.isEmpty() && map.get(0) != null) {
+                Object rating = map.get(0).get("qs_stars");
+                // 关键:显式检查null值
+                if (rating != null) {
+                    infoUser.setStar(Double.parseDouble(rating.toString()));
+                }
+
+            } else {
+                infoUser.setStar(4.5);
+            }
+
+        }
+    }
+
+    //查询所有的订单
+    @Anonymous
+    @GetMapping("/getqishouorderlist")
+    public AjaxResult getqishouorderlist(@RequestParam Integer page, @RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude, @RequestParam Integer juli, @RequestParam(defaultValue = "") String state) {
+
+        JSONArray arr = new JSONArray();
+        List<PosOrder> orlist;
+        if (!"".equals(state)) {
+            if (state.equals("z02")) {
+                orlist = posOrderMapper.getz02(longitude, latitude, (page - 1) * 20, juli);
+            } else if (state.equals("z234")) {
+                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 2, 4);
+            } else if (state.equals("z23")) {
+                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 2, 3);
+            } else if (state.equals("z34")) {
+                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 3, 4);
+            } else if (state.equals("z6789")) {
+                orlist = posOrderMapper.getz234(longitude, latitude, (page - 1) * 20, juli, 6, 9);
+            } else {
+                orlist = posOrderMapper.getstate(longitude, latitude, (page - 1) * 20, juli, state);
+            }
+        } else {
+            orlist = posOrderMapper.getqisjvli(longitude, latitude, (page - 1) * 20, juli);
+        }
+        for (int i = 0; i < orlist.size(); i++) {
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id", orlist.get(i).getId());
+            org.put("ddId", orlist.get(i).getDdId());
+            org.put("shanghu", infoUserService.getById(orlist.get(i).getShId()));
+            org.put("store", posStoreService.getById(orlist.get(i).getMdId()));
+            org.put("cretim", sdf.format(orlist.get(i).getCretim()));
+            org.put("shdzId", orlist.get(i).getShdzId());
+            org.put("shaddress", orlist.get(i).getShAddress() == null ? infoAddressService.getById(orlist.get(i).getShdzId()) : JSONObject.parseObject(orlist.get(i).getShAddress()));
+            org.put("user", infoUserService.getById(orlist.get(i).getUserId()));
+            org.put("amount", orlist.get(i).getAmount());
+            org.put("kefuState", orlist.get(i).getKefuState());
+            org.put("kefuContent", orlist.get(i).getKefuContent());
+            org.put("kefuRepeat", orlist.get(i).getKefuRepeat());
+            org.put("repeatDdId", orlist.get(i).getRepeatDdId());
+            org.put("remarks", orlist.get(i).getRemarks());
+            org.put("state", orlist.get(i).getState());
+            org.put("type", orlist.get(i).getType());
+            org.put("jvli", orlist.get(i).getJvli());
+            DecimalFormat jl = new DecimalFormat("#.0");
+            org.put("qsjvli", jl.format(orlist.get(i).getJuli()));
+            org.put("freight", orlist.get(i).getFreight());
+            org.put("delryTime", orlist.get(i).getDelryTime());
+            org.put("qsId", orlist.get(i).getQsId());
+            org.put("payUrl", orlist.get(i).getPayUrl());
+            org.put("diningStatus", orlist.get(i).getDiningStatus());
+            org.put("food", JSONArray.parseArray(orlist.get(i).getFood()));
+            org.put("collectPayment", orlist.get(i).getCollectPayment());
+//            org.put("activity",salesPromotionService.getById(orlist.get(i).getActivity()));
+
+            org.put("activity", orlist.get(i).getActivity());
+            org.put("mdActivity", orlist.get(i).getMdActivity());
+            org.put("salesReduction", orlist.get(i).getSalesReduction());
+            org.put("mdSalesReduction", orlist.get(i).getMdSalesReduction());
+            org.put("salesName", orlist.get(i).getSalesName());
+            org.put("mdSalesName", orlist.get(i).getMdSalesName());
+            org.put("mdDiscountAmount", orlist.get(i).getMdDiscountAmount());
+            org.put("discountAmount", orlist.get(i).getDiscountAmount());
+            org.put("mdYhId", orlist.get(i).getMdYhId());
+            org.put("mdYhName", orlist.get(i).getMdYhName());
+            org.put("yhId", orlist.get(i).getYhId());
+            org.put("yhName", orlist.get(i).getYhName());
+            org.put("points", orlist.get(i).getPoints());
+            org.put("pointsReduction", orlist.get(i).getPointsReduction());
+            org.put("sdTime", orlist.get(i).getSdTime());
+            org.put("payType", orlist.get(i).getPayType());
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+    //查询骑手的订单
+    @Anonymous
+    @Auth
+    @GetMapping("/getqsorderlist")
+    public AjaxResult getqsorderlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size, @RequestParam(defaultValue = "") String state) {
+        logger.info("骑手token:" + token);
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosOrder> palist = new Page<>(page, size);
+        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("cretim");
+        queryWrapper.eq("qs_id", id);
+        if (!"".equals(state)) {
+            if (state.equals("z234")) {
+                queryWrapper.in("state", 2, 3, 4);
+            } else if (state.equals("z23")) {
+                queryWrapper.in("state", 2, 3);
+            } else if (state.equals("z34")) {
+                queryWrapper.in("state", 3, 4);
+            } else if (state.equals("z6789")) {
+                queryWrapper.in("state", 6, 7, 8, 9);
+            } else if (state.equals("z678911")) {
+                queryWrapper.in("state", 6, 7, 8, 9, 11);
+            } else {
+                queryWrapper.eq("state", state);
+            }
+        }
+        IPage<PosOrder> list = posOrderService.page(palist, queryWrapper);
+        List<PosOrder> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        for (int i = 0; i < orlist.size(); i++) {
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id", orlist.get(i).getId());
+            org.put("ddId", orlist.get(i).getDdId());
+            org.put("shanghu", infoUserService.getById(orlist.get(i).getShId()));
+            org.put("store", posStoreService.getById(orlist.get(i).getMdId()));
+            org.put("cretim", sdf.format(orlist.get(i).getCretim()));
+            org.put("shdzId", orlist.get(i).getShdzId());
+            org.put("shaddress", orlist.get(i).getShAddress() == null ? infoAddressService.getById(orlist.get(i).getShdzId()) : JSONObject.parseObject(orlist.get(i).getShAddress()));
+            org.put("user", infoUserService.getById(orlist.get(i).getUserId()));
+            org.put("qishou", infoUserService.getById(orlist.get(i).getQsId()));
+            org.put("amount", orlist.get(i).getAmount());
+            org.put("kefuState", orlist.get(i).getKefuState());
+            org.put("kefuContent", orlist.get(i).getKefuContent());
+            org.put("kefuRepeat", orlist.get(i).getKefuRepeat());
+            org.put("repeatDdId", orlist.get(i).getRepeatDdId());
+            org.put("remarks", orlist.get(i).getRemarks());
+            org.put("state", orlist.get(i).getState());
+            org.put("type", orlist.get(i).getType());
+            org.put("jvli", orlist.get(i).getJvli());
+            org.put("freight", orlist.get(i).getFreight());
+            org.put("delryTime", orlist.get(i).getDelryTime());
+            org.put("diningStatus", orlist.get(i).getDiningStatus());
+            org.put("food", JSONArray.parseArray(orlist.get(i).getFood()));
+            org.put("collectPayment", orlist.get(i).getCollectPayment());
+//            org.put("activity",salesPromotionService.getById(orlist.get(i).getActivity()));
+            org.put("sqImg", orlist.get(i).getQsImg());
+//            org.put("discountAmount",orlist.get(i).getDiscountAmount());
+
+            org.put("activity", orlist.get(i).getActivity());
+            org.put("mdActivity", orlist.get(i).getMdActivity());
+            org.put("salesReduction", orlist.get(i).getSalesReduction());
+            org.put("mdSalesReduction", orlist.get(i).getMdSalesReduction());
+            org.put("salesName", orlist.get(i).getSalesName());
+            org.put("mdSalesName", orlist.get(i).getMdSalesName());
+            org.put("mdDiscountAmount", orlist.get(i).getMdDiscountAmount());
+            org.put("discountAmount", orlist.get(i).getDiscountAmount());
+            org.put("mdYhId", orlist.get(i).getMdYhId());
+            org.put("mdYhName", orlist.get(i).getMdYhName());
+            org.put("yhId", orlist.get(i).getYhId());
+            org.put("yhName", orlist.get(i).getYhName());
+            org.put("points", orlist.get(i).getPoints());
+            org.put("pointsReduction", orlist.get(i).getPointsReduction());
+            org.put("sdTime", orlist.get(i).getSdTime());
+            org.put("payType", orlist.get(i).getPayType());
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+    //查询商家的订单
+    @Anonymous
+    @Auth
+    @GetMapping("/getstoreorderlist")
+    public AjaxResult getstoreorderlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size, @RequestParam String mdId, @RequestParam(defaultValue = "") String state, @RequestParam(defaultValue = "") String diningStatus) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosOrder> palist = new Page<>(page, size);
+        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("cretim");
+        queryWrapper.eq("sh_id", id);
+        System.out.println("商户id:" + id);
+        queryWrapper.eq("md_id", mdId);
+        if (!"".equals(state)) {
+            if (state.equals("z01")) {
+                queryWrapper.eq("state", 0).and(posOrderQueryWrapper -> posOrderQueryWrapper.eq("collect_payment", "1")).and(posOrderQueryWrapper -> posOrderQueryWrapper.eq("type", 1)).or().eq("state", 1).and(posOrderQueryWrapper -> posOrderQueryWrapper.eq("sh_id", id)).and(posOrderQueryWrapper -> posOrderQueryWrapper.eq("md_id", mdId));
+            } else if (state.equals("z234")) {
+                queryWrapper.in("state", 2, 3, 4);
+            } else if (state.equals("z23")) {
+                queryWrapper.in("state", 2, 3);
+            } else if (state.equals("z34")) {
+                queryWrapper.in("state", 3, 4);
+            } else if (state.equals("z678911")) {
+                queryWrapper.in("state", 6, 7, 8, 9, 11);
+            } else {
+                queryWrapper.eq("state", state);
+            }
+        }
+        if (!"".equals(diningStatus)) {
+            queryWrapper.eq("dining_status", diningStatus);
+        }
+        IPage<PosOrder> list = posOrderService.page(palist, queryWrapper);
+        List<PosOrder> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        for (int i = 0; i < orlist.size(); i++) {
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id", orlist.get(i).getId());
+            org.put("ddId", orlist.get(i).getDdId());
+            org.put("shanghu", infoUserService.getById(orlist.get(i).getShId()));
+            org.put("store", posStoreService.getById(orlist.get(i).getMdId()));
+            org.put("cretim", sdf.format(orlist.get(i).getCretim()));
+            org.put("shdzId", orlist.get(i).getShdzId());
+            org.put("shaddress", orlist.get(i).getShAddress() == null ? infoAddressService.getById(orlist.get(i).getShdzId()) : JSONObject.parseObject(orlist.get(i).getShAddress()));
+            org.put("user", infoUserService.getById(orlist.get(i).getUserId()));
+            org.put("amount", orlist.get(i).getAmount());
+            org.put("kefuState", orlist.get(i).getKefuState());
+            org.put("kefuContent", orlist.get(i).getKefuContent());
+            org.put("kefuRepeat", orlist.get(i).getKefuRepeat());
+            org.put("repeatDdId", orlist.get(i).getRepeatDdId());
+            org.put("remarks", orlist.get(i).getRemarks());
+            org.put("state", orlist.get(i).getState());
+            org.put("type", orlist.get(i).getType());
+            org.put("jvli", orlist.get(i).getJvli());
+            org.put("freight", orlist.get(i).getFreight());
+            org.put("delryTime", orlist.get(i).getDelryTime());
+            org.put("diningStatus", orlist.get(i).getDiningStatus());
+            org.put("collectPayment", orlist.get(i).getCollectPayment());
+            org.put("discountAmount", orlist.get(i).getDiscountAmount());
+            org.put("food", JSONArray.parseArray(orlist.get(i).getFood()));
+            org.put("activity", orlist.get(i).getActivity());
+            org.put("mdActivity", orlist.get(i).getMdActivity());
+            org.put("salesReduction", orlist.get(i).getSalesReduction());
+            org.put("mdSalesReduction", orlist.get(i).getMdSalesReduction());
+            org.put("salesName", orlist.get(i).getSalesName());
+            org.put("mdSalesName", orlist.get(i).getMdSalesName());
+            org.put("mdDiscountAmount", orlist.get(i).getMdDiscountAmount());
+            org.put("discountAmount", orlist.get(i).getDiscountAmount());
+            org.put("mdYhId", orlist.get(i).getMdYhId());
+            org.put("mdYhName", orlist.get(i).getMdYhName());
+            org.put("yhId", orlist.get(i).getYhId());
+            org.put("yhName", orlist.get(i).getYhName());
+            org.put("points", orlist.get(i).getPoints());
+            org.put("pointsReduction", orlist.get(i).getPointsReduction());
+            org.put("sdTime", orlist.get(i).getSdTime());
+            org.put("payType", orlist.get(i).getPayType());
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+    //查询用户的订单
+    @Anonymous
+    @Auth
+    @GetMapping("/getorderlist")
+    public AjaxResult getorderlist(@RequestHeader String token, @RequestParam Integer page, @RequestParam Integer size, @RequestParam(defaultValue = "") String state) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<PosOrder> palist = new Page<>(page, size);
+        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("cretim");
+        queryWrapper.eq("user_id", id);
+        if (!"".equals(state)) {
+            if (state.equals("z23412")) {
+                queryWrapper.in("state", 2, 3, 4, 12);
+            } else if (state.equals("z23")) {
+                queryWrapper.in("state", 2, 3);
+            } else if (state.equals("z34")) {
+                queryWrapper.in("state", 3, 4);
+            } else if (state.equals("z678911")) {
+                queryWrapper.in("state", 6, 7, 8, 9, 11);
+            } else {
+                queryWrapper.eq("state", state);
+            }
+        }
+        // 添加排除条件:state=0且collect_payment=0的数据
+        queryWrapper.apply("NOT (state = 0 AND collect_payment = 0)");
+        IPage<PosOrder> list = posOrderService.page(palist, queryWrapper);
+        List<PosOrder> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        for (int i = 0; i < orlist.size(); i++) {
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id", orlist.get(i).getId());
+            org.put("ddId", orlist.get(i).getDdId());
+            org.put("shanghu", infoUserService.getById(orlist.get(i).getShId()));
+            org.put("store", posStoreService.getById(orlist.get(i).getMdId()));
+            org.put("cretim", sdf.format(orlist.get(i).getCretim()));
+            org.put("shdzId", orlist.get(i).getShdzId());
+            org.put("shaddress", orlist.get(i).getShAddress() == null ? infoAddressService.getById(orlist.get(i).getShdzId()) : JSONObject.parseObject(orlist.get(i).getShAddress()));
+            org.put("user", infoUserService.getById(orlist.get(i).getUserId()));
+            org.put("amount", orlist.get(i).getAmount());
+            org.put("kefuState", orlist.get(i).getKefuState());
+            org.put("kefuContent", orlist.get(i).getKefuContent());
+            org.put("kefuRepeat", orlist.get(i).getKefuRepeat());
+            org.put("repeatDdId", orlist.get(i).getRepeatDdId());
+            org.put("remarks", orlist.get(i).getRemarks());
+            org.put("state", orlist.get(i).getState());
+            org.put("type", orlist.get(i).getType());
+            org.put("jvli", orlist.get(i).getJvli());
+            org.put("freight", orlist.get(i).getFreight());
+            org.put("delryTime", orlist.get(i).getDelryTime());
+            org.put("payUrl", orlist.get(i).getPayUrl());
+            org.put("collectPayment", orlist.get(i).getCollectPayment());
+            org.put("food", JSONArray.parseArray(orlist.get(i).getFood()));
+//            org.put("activity",salesPromotionService.getById(orlist.get(i).getActivity()));
+            org.put("activity", orlist.get(i).getActivity());
+            org.put("mdActivity", orlist.get(i).getMdActivity());
+            org.put("salesReduction", orlist.get(i).getSalesReduction());
+            org.put("mdSalesReduction", orlist.get(i).getMdSalesReduction());
+            org.put("salesName", orlist.get(i).getSalesName());
+            org.put("mdSalesName", orlist.get(i).getMdSalesName());
+            org.put("mdDiscountAmount", orlist.get(i).getMdDiscountAmount());
+            org.put("discountAmount", orlist.get(i).getDiscountAmount());
+            org.put("mdYhId", orlist.get(i).getMdYhId());
+            org.put("mdYhName", orlist.get(i).getMdYhName());
+            org.put("yhId", orlist.get(i).getYhId());
+            org.put("yhName", orlist.get(i).getYhName());
+            org.put("points", orlist.get(i).getPoints());
+            org.put("pointsReduction", orlist.get(i).getPointsReduction());
+            org.put("sdTime", orlist.get(i).getSdTime());
+            org.put("payType", orlist.get(i).getPayType());
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+    //    @Anonymous
+//    @GetMapping("/sssaaaa")
+//    public AjaxResult sssaaaa(@RequestParam String aa,@RequestParam String bb){
+//        DateUtil dateUtil = new DateUtil();
+//        Boolean sbsj = dateUtil.isLegalTime(aa,bb);
+//        return success(sbsj);
+//    }
+    //添加新订单
+    @SneakyThrows
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
+    @PostMapping("/addorder")
+    public AjaxResult addorder(@RequestHeader String token, @RequestBody OrderDTO orderDTO) {
+        long methodStart = System.currentTimeMillis(); // 记录方法开始时间
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+        Integer xiadanjiaoyan = orderDTO.getXiadanjiaoyan();
+        if (xiadanjiaoyan == null || !xiadanjiaoyan.equals(2)) {
+            return error(MessageUtils.message("no.xiadanyz.message"));
+        }
+
+        System.out.println("========== 接收到的orderDTO ==========");
+        System.out.println(mapper.writeValueAsString(orderDTO));
+        JwtUtil jwtUtil = new JwtUtil();
+        PayPush push = new PayPush();
+        DateUtil dateUtil = new DateUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<OperatingHours> wrapper = new QueryWrapper<>();
+        wrapper.eq("md_id", orderDTO.getMdId());
+        List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
+        PosStore store = posStoreService.getById(orderDTO.getMdId());
+
+        JSONObject usdizhi = new JSONObject();
+        if (orderDTO.getType() != null && orderDTO.getType().equals(0L)) {
+            InfoAddress usadd = infoAddressService.getById(orderDTO.getShdzId());
+            if (usadd == null) {
+                return error(MessageUtils.message("no.address.not.exist"));
+            } else {
+                usdizhi.put("name", usadd.getName());
+                usdizhi.put("phone", usadd.getPhone());
+                usdizhi.put("address", usadd.getAddress());
+                usdizhi.put("country", usadd.getCountry());
+                usdizhi.put("province", usadd.getProvince());
+                usdizhi.put("city", usadd.getCity());
+                usdizhi.put("area", usadd.getArea());
+                usdizhi.put("longitude", String.valueOf(usadd.getLongitude()));
+                usdizhi.put("latitude", String.valueOf(usadd.getLatitude()));
+            }
+        }
+        if (hourslist.size() == 0) {
+            return error(MessageUtils.message("no.mendian.not.set.business.hours"));
+        }
+        if (store.getState() == 1) {
+            return error(MessageUtils.message("no.mendian.is.closed"));
+        }
+        Boolean dayang = false;
+        for (int i = 0; i < hourslist.size(); i++) {
+            Boolean sbsj = dateUtil.isLegalTime(hourslist.get(i).getStartTime(), hourslist.get(i).getEndTime());
+            if (sbsj == true) {
+                dayang = true;
+            }
+        }
+        if (dayang == false) {
+            return error(MessageUtils.message("no.mendian.is.closed"));
+        }
+        //订单金额限制100万改为200万
+        if (orderDTO.getCollectPayment().equals("1") && orderDTO.getAmount() > 2000000) {
+            return error(MessageUtils.message("no.cash_on_delivery_amount.exceed.limit_amount"));
+        }
+        QueryWrapper<PosOrder> query = new QueryWrapper<>();
+        query.eq("user_id", id);
+        query.eq("collect_payment", "1");
+        query.notIn("state", 5, 10, 11);
+        List<PosOrder> posOrders = posOrderService.list(query);
+        System.out.println("到付信息:user_id=" + id + " ,到付数量:" + posOrders.size());
+        //到付能存在2单未完成,第3单弹出提示
+        if (posOrders.size() >= 2 && orderDTO.getCollectPayment().equals("1")) {
+            return error(MessageUtils.message("no.exist.cash_on_delivery_order.incomplete"));
+        }
+        JSONArray jsonArray = orderDTO.getFoodlist();
+        Map<Long,Long> map = new HashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            Long foodid = jsonArray.getJSONObject(i).getLong("id");
+            PosFood food = posFoodService.getById(foodid);
+            if (food == null) {
+                return error(jsonArray.getJSONObject(i).getString("name") + MessageUtils.message("no.goods.not.exist"));
+            } else {
+                if (food.getStackingUp().equals("1")) {
+                    return error(food.getName() + MessageUtils.message("no.goods.is.off.shelf"));
+                }
+            }
+            Long num = jsonArray.getJSONObject(i).getLong("number");
+            map.put(foodid,num);
+        }
+        VipUserQuanyi yh = null;
+        VipUserQuanyi mdYh = null;
+        if (ObjectUtil.isNotNull(orderDTO.getYhId()) && ObjectUtil.notEqual(orderDTO.getYhId(), 0L)) {
+            LambdaQueryWrapper<VipUserQuanyi> yhQuery = new LambdaQueryWrapper<>();
+            yhQuery.eq(VipUserQuanyi::getId, orderDTO.getYhId());
+            yh = userQuanyiService.getOne(yhQuery);
+            if (yh == null) {
+                throw new ServiceException("no.userquanyi.not.exist");
+            }
+            if (yh.getState().equals("1")) {
+                throw new ServiceException("userquanyi.isUsed");
+            }
+        }
+        if (ObjectUtil.isNotNull(orderDTO.getMdYhId()) && ObjectUtil.notEqual(orderDTO.getMdYhId(), 0L)) {
+            LambdaQueryWrapper<VipUserQuanyi> mdYhquery = new LambdaQueryWrapper<>();
+            mdYhquery.eq(VipUserQuanyi::getId, orderDTO.getMdYhId());
+            mdYh = userQuanyiService.getOne(mdYhquery);
+            if (mdYh == null) {
+                throw new ServiceException("no.userquanyi.not.exist");
+            }
+            if (mdYh.getState().equals("1")) {
+                throw new ServiceException("userquanyi.isUsed");
+            }
+        }
+        SalesPromotion activity = null;
+        SalesPromotion mdActivity = null;
+        if (ObjectUtil.isNotNull(orderDTO.getActivity()) && ObjectUtil.notEqual(orderDTO.getActivity(), 0L)) {
+            LambdaQueryWrapper<SalesPromotion> saleQuery = new LambdaQueryWrapper<>();
+            saleQuery.eq(SalesPromotion::getId, orderDTO.getActivity());
+            activity = salesPromotionService.getOne(saleQuery);
+            if (activity == null) {
+                throw new ServiceException("no.activity.not.exist");
+            }
+//            if (yh.getState().equals("1")) {
+//                throw new ServiceException("userquanyi.isUsed");
+//            }
+        }
+        if (ObjectUtil.isNotNull(orderDTO.getMdActivity()) && ObjectUtil.notEqual(orderDTO.getMdActivity(), 0L)) {
+            LambdaQueryWrapper<SalesPromotion> saleQuery = new LambdaQueryWrapper<>();
+            saleQuery.eq(SalesPromotion::getId, orderDTO.getMdActivity());
+            mdActivity = salesPromotionService.getOne(saleQuery);
+
+            if (mdActivity == null) {
+                throw new ServiceException("no.activity.not.exist");
+            }
+
+        }
+        PosOrder posOrder = new PosOrder();
+        AjaxResult posOrderResult = redeePoints(orderDTO, Long.valueOf(id));
+        if (!posOrderResult.get("code").equals(200)) {
+            return posOrderResult;
+        } else {
+            posOrder.setPoints(orderDTO.getPoints());
+            posOrder.setPointsReduction(orderDTO.getPointsReduction());
+        }
+        posOrder.setDdId(orderDTO.getDdId());
+        posOrder.setShId(orderDTO.getShId());
+        posOrder.setMdId(orderDTO.getMdId());
+        posOrder.setShdzId(orderDTO.getShdzId());
+        posOrder.setShAddress(JSON.toJSONString(usdizhi));
+        posOrder.setUserId(Long.valueOf(id));
+        posOrder.setAmount(orderDTO.getAmount());
+        posOrder.setRemarks(orderDTO.getRemarks());
+        posOrder.setType(orderDTO.getType());
+        posOrder.setDelryTime(orderDTO.getDelryTime());
+        posOrder.setFood(jsonArray.toString());
+        posOrder.setState(0L);
+
+        posOrder.setJvli(orderDTO.getJvli());
+        posOrder.setFreight(orderDTO.getFreight());
+        posOrder.setLongitude(orderDTO.getLongitude());
+        posOrder.setLatitude(orderDTO.getLatitude());
+        posOrder.setDiningStatus(orderDTO.getDiningStatus());
+        posOrder.setQsId(orderDTO.getQsId());
+        posOrder.setJuli(orderDTO.getJuli());
+        posOrder.setPayUrl(orderDTO.getPayUrl());
+        posOrder.setCollectPayment(orderDTO.getCollectPayment());
+
+        // posOrder.setCretim(dateUtil.getDatetim(orderDTO.getCretim()));
+        //创建时间改成后端生成
+        posOrder.setCretim(new Date());
+
+        if (yh != null) {
+            posOrder.setYhName(yh.getName());
+            posOrder.setYhId(orderDTO.getYhId());
+            posOrder.setDiscountAmount(orderDTO.getDiscountAmount());
+        }
+
+        if (mdYh != null) {
+            posOrder.setMdYhId(orderDTO.getMdYhId());
+            posOrder.setMdYhName(mdYh.getName());
+            posOrder.setMdDiscountAmount(orderDTO.getMdDiscountAmount());
+        }
+
+        if (mdActivity != null) {
+            posOrder.setMdActivity(orderDTO.getMdActivity());
+            posOrder.setMdSalesName(mdActivity.getSalesName());
+            posOrder.setMdSalesReduction(orderDTO.getMdSalesReduction());
+        }
+        if (activity != null) {
+            posOrder.setActivity(orderDTO.getActivity());
+            posOrder.setSalesName(activity.getSalesName());
+            posOrder.setSalesReduction(orderDTO.getSalesReduction());
+        }
+        //设置支付类型为货到付款
+        if ("1".equals(posOrder.getCollectPayment())) {
+            posOrder.setPayType("1");
+        }
+        Boolean org = posOrderService.saveOrUpdate(posOrder);
+        foodStatistics(map);
+        if (org) {
+            QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("user_id", id);
+            queryWrapper.eq("dd_id", posOrder.getDdId());
+            UserBilling billing = userBillingService.getOne(queryWrapper);
+            if (billing == null) {
+                UserBilling usb = new UserBilling();
+                usb.setUserId(Long.valueOf(id));
+                usb.setDdId(String.valueOf(posOrder.getDdId()));
+                usb.setMdId(posOrder.getMdId());
+                usb.setState("3");
+                usb.setType("3");
+                userBillingService.saveOrUpdate(usb);
+            }
+            QueryWrapper<UserFootprint> Wrapper = new QueryWrapper<>();
+            Wrapper.eq("user_id", id);
+            Wrapper.eq("md_id", posOrder.getMdId());
+            UserFootprint foot = userFootprintService.getOne(Wrapper);
+            DateUtil dateString = new DateUtil();
+            if (foot == null) {
+                UserFootprint usf = new UserFootprint();
+                usf.setUserId(Long.valueOf(id));
+                usf.setMdId(posOrder.getMdId());
+                usf.setCretim(dateString.GetDate());
+                userFootprintService.saveOrUpdate(usf);
+            } else {
+                foot.setCretim(dateString.GetDate());
+                userFootprintService.saveOrUpdate(foot);
+            }
+            QueryWrapper<PosOrder> querywra = new QueryWrapper<>();
+            querywra.eq("dd_id", posOrder.getDdId());
+            PosOrder order = posOrderService.getOne(querywra);
+            //货到付款、类型外卖,推送给骑手有新订单了
+            if (order.getCollectPayment().equals("1") && order.getType() == 0) {
+                sendHdfkMessage(order, push);
+            }
+
+            //存在使用优惠券的话,核销优惠券
+            redeemCoupons(yh, mdYh, order.getDdId());
+            System.out.println("========== 输出的order ==========");
+            System.out.println(mapper.writeValueAsString(order));
+            long methodEnd = System.currentTimeMillis(); // 方法结束时间
+            System.out.println("addorder 方法总执行耗时: " + (methodEnd - methodStart) + " ms");
+            return success(MessageUtils.message("no.order.submit.success"), order);
+        } else {
+            long methodEnd = System.currentTimeMillis(); // 方法结束时间
+            System.out.println("addorder 方法总执行耗时: " + (methodEnd - methodStart) + " ms");
+            return error();
+        }
+    }
+    //统计美食销售量
+    private void foodStatistics(Map<Long,Long> map) {
+        for (Map.Entry<Long, Long> entry : map.entrySet()) {
+            Long key = entry.getKey();
+            Long value = entry.getValue();
+            // 使用数据库原子UPSERT,避免并发下的竞态问题
+            foodStatisticsService.increaseNumber(key, value);
+        }
+    }
+
+    /**
+     * 货到付款发送推送
+     *
+     * @param order
+     * @param push
+     */
+    private void sendHdfkMessage(PosOrder order, PayPush push) {
+        InfoUser sh = infoUserService.getById(order.getShId());
+        push.shpush(sh.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), OrderPushBodyDto.getJson(String.valueOf(order.getDdId()), String.valueOf(order.getState()), 0));
+        pushEventService.PublisherEvent(sh.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), OrderPushBodyDto.getJson(String.valueOf(order.getDdId()), String.valueOf(order.getState()), 0));
+        long sendQsPushStart = System.currentTimeMillis(); // sendQsPush 开始时间
+        if (order.getType() == 0) {
+            sendQsPush(order, push);
+        }
+        long sendQsPushEnd = System.currentTimeMillis(); // sendQsPush 结束时间
+        System.out.println("sendQsPush 执行耗时: " + (sendQsPushEnd - sendQsPushStart) + " ms");
+    }
+
+    /**
+     * 推送可接单骑手
+     *
+     * @param order
+     * @param push
+     */
+    protected void sendQsPush(PosOrder order, PayPush push) {
+        payController.sendAcceptRiderPush(order, push, riderPositionMapper, OrderPushBodyDto.getJson(String.valueOf(order.getDdId()), String.valueOf(order.getState()), 0));
+    }
+
+
+    //核销积分
+    private AjaxResult redeePoints(OrderDTO orderDTO, Long userId) {
+        if (ObjectUtil.isNotNull(orderDTO.getPoints()) && ObjectUtil.notEqual(orderDTO.getPoints(), 0) && ObjectUtil.isNotNull(orderDTO.getPointsReduction()) && ObjectUtil.notEqual(orderDTO.getPointsReduction(), 0)) {
+            SysPointControl control = pointControlService.getById(1L);
+            if (!control.getOrderUseEnable().equals(1L)) {
+                throw new ServiceException(MessageUtils.message("no.points.use.enable"));
+            }
+            LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
+            walletQuery.eq(UserWallet::getUserId, userId);
+            UserWallet userWallet = userWalletService.getOne(walletQuery);
+            if (ObjectUtil.isNotNull(userWallet)) {
+                if (userWallet.getPointsWallet().compareTo(Long.valueOf(orderDTO.getPoints())) >= 0) {
+                    walletQuery.eq(UserWallet::getVersion, userWallet.getVersion());
+                    userWallet.setPointsWallet(userWallet.getPointsWallet() - orderDTO.getPoints());
+                    userWallet.setVersion(userWallet.getVersion() + 1);
+                    boolean update = userWalletService.update(userWallet, walletQuery);
+                    createPointTransaction(userId, Long.valueOf(orderDTO.getPoints()), userWallet.getPointsWallet(), orderDTO.getDdId(), "1");
+                    if (!update) {
+                        throw new ServiceException(MessageUtils.message("no.points.update.fail"));
+                    }
+                } else {
+                    throw new ServiceException(MessageUtils.message("no.points.insufficient"));
+                }
+            } else {
+                throw new ServiceException(MessageUtils.message("no.points.not.exist"));
+            }
+        }
+        return success();
+    }
+
+    /**
+     * 创建积分流水
+     */
+    private void createPointTransaction(Long userid, Long pointsChange, Long currentPoints, Long ddId, String type) {
+        PointsTransaction pointsTransaction = new PointsTransaction();
+        pointsTransaction.setUserId(userid);
+        if (type.equals("1")) {
+            pointsTransaction.setPointsChange("-" + pointsChange);
+            pointsTransaction.setType("1");
+        }
+        if (type.equals("2")) {
+            pointsTransaction.setPointsChange("+" + pointsChange);
+            pointsTransaction.setType("2");
+        }
+        pointsTransaction.setCurrentPoints(currentPoints.toString());
+        pointsTransaction.setDdId(ddId);
+        pointsTransaction.setCreateTime(new Date());
+        pointsTransactionService.save(pointsTransaction);
+    }
+
+
+    /**
+     * 核销优惠券
+     *
+     * @param orderId
+     */
+    private void redeemCoupons(VipUserQuanyi yh, VipUserQuanyi mdYh, Long orderId) {
+        if (ObjectUtil.isNotNull(yh)) {
+            yh.setState("1");
+            yh.setOrderId(orderId);
+            yh.setUpdateTime(new Date());
+            userQuanyiService.saveOrUpdate(yh);
+        }
+        if (ObjectUtil.isNotNull(mdYh)) {
+            mdYh.setState("1");
+            mdYh.setOrderId(orderId);
+            mdYh.setUpdateTime(new Date());
+            userQuanyiService.saveOrUpdate(mdYh);
+        }
+    }
+
+    /**
+     * 查询posorder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosOrder posOrder) {
+        startPage();
+        String[] dr = posOrder.getDateRange();
+        if (dr != null && dr.length == 2) {
+            posOrder.setCretimStart(dr[0]);
+            posOrder.setCretimEnd(dr[1]);
+        }
+        List<PosOrder> list = posOrderService.selectPosOrderList(posOrder);
+        if (list != null && list.size() > 0) {
+            for (PosOrder od : list) {
+                JSONArray foodArr = JSONArray.parseArray(od.getFood());
+                long priceAll = new Integer(0);
+                for (int i = 0; i < foodArr.size(); i++) {
+                    JSONObject obj = foodArr.getJSONObject(i);
+                    BigDecimal price = obj.getBigDecimal("price");
+                    if (price == null) continue;
+                    Integer priceDb = price.intValue();
+                    BigDecimal otherprice = obj.getBigDecimal("otherPrice");
+                    if (otherprice != null && otherprice.doubleValue() > 0) {
+                        priceDb += otherprice.intValue();
+                    }
+                    Long num = obj.getLong("number");
+                    if (num == null) continue;
+                    priceAll += (priceDb * num.longValue());
+                }
+                od.setPriceAll(priceAll + "");
+                Long atv = od.getActivity();
+                if (atv != null && atv.longValue() > 0) {
+                    SalesPromotion salesPromotion = salesPromotionService.getById(atv);
+                    if (salesPromotion != null) {
+                        od.setSalesName(salesPromotion.getSalesName());
+//                        od.setSalesReduction(""+salesPromotion.getSalesReduction());
+                    }
+                }
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询sh posorder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:shlist1')")
+    @GetMapping("/shlist1")
+    public TableDataInfo shlist1(PosOrder posOrder) {
+        startPage();
+        String[] dr = posOrder.getDateRange();
+        if (dr != null && dr.length == 2) {
+            posOrder.setCretimStart(dr[0]);
+            posOrder.setCretimEnd(dr[1]);
+        }
+        List<PosOrder> list = posOrderService.selectPosOrderShList(posOrder);
+        if (list != null && list.size() > 0) {
+            for (PosOrder od : list) {
+                //查询用户留言
+                PosAppeal posAppeal = new PosAppeal();
+                posAppeal.setDdId(od.getDdId());
+                posAppeal.setUserType("0");
+                List<PosAppeal> aplist = posAppealService.selectPosAppealList(posAppeal);
+                int s = 0;
+                if (aplist != null) s = aplist.size();
+                od.setAppealCount(s + "");
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询sh posorder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:shlist2')")
+    @GetMapping("/shlist2")
+    public TableDataInfo shlist2(PosOrder posOrder) {
+        startPage();
+        String[] dr = posOrder.getDateRange();
+        if (dr != null && dr.length == 2) {
+            posOrder.setCretimStart(dr[0]);
+            posOrder.setCretimEnd(dr[1]);
+        }
+        List<PosOrder> list = posOrderService.selectPosOrderShList(posOrder);
+        if (list != null && list.size() > 0) {
+            for (PosOrder od : list) {
+                //查询用户留言
+                PosAppeal posAppeal = new PosAppeal();
+                posAppeal.setDdId(od.getDdId());
+                posAppeal.setUserType("1");
+                List<PosAppeal> aplist = posAppealService.selectPosAppealList(posAppeal);
+                int s = 0;
+                if (aplist != null) s = aplist.size();
+                od.setAppealCount(s + "");
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询sh posorder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:shlist3')")
+    @GetMapping("/shlist3")
+    public TableDataInfo shlist3(PosOrder posOrder) {
+        startPage();
+        String[] dr = posOrder.getDateRange();
+        if (dr != null && dr.length == 2) {
+            posOrder.setCretimStart(dr[0]);
+            posOrder.setCretimEnd(dr[1]);
+        }
+        List<PosOrder> list = posOrderService.selectPosOrderShList(posOrder);
+        if (list != null && list.size() > 0) {
+            for (PosOrder od : list) {
+                //查询用户留言
+                PosAppeal posAppeal = new PosAppeal();
+                posAppeal.setDdId(od.getDdId());
+                posAppeal.setUserType("2");
+                List<PosAppeal> aplist = posAppealService.selectPosAppealList(posAppeal);
+                int s = 0;
+                if (aplist != null) s = aplist.size();
+                od.setAppealCount(s + "");
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出posorder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:export')")
+    @Log(title = "posorder", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosOrder posOrder) {
+        List<PosOrder> list = posOrderService.selectPosOrderList(posOrder);
+        if (list != null && list.size() > 0) {
+            for (PosOrder od : list) {
+                JSONArray foodArr = JSONArray.parseArray(od.getFood());
+                long priceAll = new Integer(0);
+                for (int i = 0; i < foodArr.size(); i++) {
+                    JSONObject obj = foodArr.getJSONObject(i);
+                    BigDecimal price = obj.getBigDecimal("price");
+                    if (price == null) continue;
+                    Integer priceDb = price.intValue();
+                    //商品规格价格
+                    BigDecimal otherprice = obj.getBigDecimal("otherPrice");
+                    if (otherprice != null && otherprice.doubleValue() > 0) {
+                        priceDb += otherprice.intValue();
+                    }
+                    Long num = obj.getLong("number");
+                    if (num == null) continue;
+                    priceAll += (priceDb * num.longValue());
+                }
+                od.setPriceAll(priceAll + "");
+                Long atv = od.getActivity();
+                if (atv != null && atv.longValue() > 0) {
+                    SalesPromotion salesPromotion = salesPromotionService.getById(atv);
+                    if (salesPromotion != null) {
+                        od.setSalesName(salesPromotion.getSalesName());
+//                        od.setSalesReduction(""+salesPromotion.getSalesReduction());
+                    }
+                }
+            }
+        }
+        ExcelUtil<PosOrder> util = new ExcelUtil<PosOrder>(PosOrder.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.posorder"));
+    }
+
+    /**
+     * 获取posorder详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(posOrderService.selectPosOrderById(id));
+    }
+
+    /**
+     * 新增posorder
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:add')")
+    @Log(title = "posorder", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosOrder posOrder) {
+        return toAjax(posOrderService.insertPosOrder(posOrder));
+    }
+
+    /**
+     * 修改posorder
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @PreAuthorize("@ss.hasPermi('system:order:edit')")
+    @Log(title = "posorder", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosOrder posOrder) {
+        //送达时间
+        if (posOrder.getState() == 12) {
+            posOrder.setSdTime(new Date());
+        }
+        if (posOrder.getState() == 7) {
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            wrapper.eq("dd_id", posOrder.getId());
+            List<UserBilling> billing = userBillingService.list(wrapper);
+            for (int i = 0; i < billing.size(); i++) {
+                UserBilling user = new UserBilling();
+                user.setId(billing.get(i).getId());
+                user.setState("1");
+                userBillingService.saveOrUpdate(user);
+            }
+            //退款、作废退回积分
+            if ((posOrder.getState() == 7 || posOrder.getState() == 11) && posOrder.getPoints() != null && posOrder.getPoints() > 0) {
+                returnPoints(posOrder.getUserId(), posOrder.getId(), Long.valueOf(posOrder.getPoints()));
+            }
+            return toAjax(posOrderService.updatePosOrder(posOrder));
+        } else {
+            if (posOrder.getKefuState().intValue() == 1) {
+                posOrder.setState(5L);
+            }
+            return toAjax(posOrderService.updatePosOrder(posOrder));
+        }
+    }
+
+
+    /**
+     * 订单取消、退款成功返回积分
+     *
+     * @param userId
+     * @param ddId
+     * @param points
+     */
+    public void returnPoints(Long userId, Long ddId, Long points) {
+        LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
+        walletQuery.eq(UserWallet::getUserId, userId);
+        UserWallet userWallet = userWalletService.getOne(walletQuery);
+        PointsTransaction transaction = pointsTransactionService.getOne(new LambdaQueryWrapper<PointsTransaction>().eq(PointsTransaction::getDdId, ddId).eq(PointsTransaction::getType, "2"));
+        //该订单不存在退回的积分记录
+        if (ObjectUtil.isNotNull(userWallet) && transaction == null) {
+            walletQuery.eq(UserWallet::getVersion, userWallet.getVersion());
+            userWallet.setPointsWallet(userWallet.getPointsWallet() + points);
+            userWallet.setVersion(userWallet.getVersion() + 1);
+            boolean update = userWalletService.update(userWallet, walletQuery);
+            createPointTransaction(userId, Long.valueOf(points), userWallet.getPointsWallet(), ddId, "2");
+            if (!update) {
+                throw new ServiceException(MessageUtils.message("no.points.update.fail"));
+            }
+        } else {
+            throw new ServiceException(MessageUtils.message("no.points.insufficient"));
+        }
+    }
+
+
+    /**
+     * 删除posorder
+     */
+    @PreAuthorize("@ss.hasPermi('system:order:remove')")
+    @Log(title = "posorder", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(posOrderService.deletePosOrderByIds(ids));
+    }
+
+    /**
+     * 测试推送消息
+     *
+     * @param cid
+     * @return
+     */
+
+    @Anonymous
+    @RequestMapping(value = "/testPushMessage", method = {RequestMethod.GET})
+    public AjaxResult testPushMessage(String cid, String title, String content, String body) {
+        PayPush push = new PayPush();
+        push.qspush(cid, title, content, body);
+        return AjaxResult.success();
+    }
+
+
+    /**
+     * 获取配送中的订单位置信息
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getPsOrdersPosition")
+    public AjaxResult getPsOrdersPosition(@RequestHeader String token) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        List<OrderPositionInfo> result = new ArrayList<>();
+        QueryWrapper<PosOrder> wrapper = new QueryWrapper<>();
+
+        wrapper.eq("user_id", id).apply("(pay_type!=1 and (state = 1 or state = 2 or state = 3 or state = 4) or (pay_type=1 and (state = 0 or state = 1 or state = 2 or state = 3 or state = 4)))").orderByDesc("cretim");
+        List<PosOrder> list = posOrderService.list(wrapper);
+        if (!list.isEmpty()) {
+            List<Long> qsIds = list.stream().map(PosOrder::getQsId).collect(Collectors.toList());
+            List<InfoUser> users = new ArrayList<>();
+            if (!qsIds.isEmpty()) {
+                LambdaQueryWrapper<InfoUser> userWrapper = new LambdaQueryWrapper<>();
+                userWrapper.in(InfoUser::getUserId, qsIds);
+                users = infoUserService.list(userWrapper);
+            }
+            List<Long> mdIds = list.stream().map(PosOrder::getMdId).collect(Collectors.toList());
+            LambdaQueryWrapper<PosStore> mdWrapper = new LambdaQueryWrapper<PosStore>().in(PosStore::getId, mdIds);
+            List<PosStore> stores = posStoreService.list(mdWrapper);
+            List<RiderPosition> riderPositions = new ArrayList<>();
+            if (!qsIds.isEmpty()) {
+                riderPositions = riderPositionService.list(new LambdaQueryWrapper<RiderPosition>().in(RiderPosition::getRiderId, qsIds));
+            }
+            for (PosOrder posOrder : list) {
+                OrderPositionInfo orderPositionInfo = new OrderPositionInfo();
+                orderPositionInfo.setDdId(posOrder.getDdId());
+                orderPositionInfo.setOrderState(posOrder.getState());
+                orderPositionInfo.setDelryTime(posOrder.getDelryTime());
+                orderPositionInfo.setYjsdTime(posOrder.getYjsdTime());
+                orderPositionInfo.setDiningStatus(posOrder.getDiningStatus());
+                orderPositionInfo.setPayType(posOrder.getPayType());
+
+                if (posOrder.getQsId() != null) {
+                    QsDto qsDto = new QsDto();
+                    users.stream().filter(infoUser -> infoUser.getUserId().equals(posOrder.getQsId())).findFirst().ifPresent(user -> {
+                        qsDto.setUserName(user.getUserName());
+                        qsDto.setNickName(user.getNickName());
+                    });
+                    qsDto.setDelryTime(posOrder.getDelryTime());
+                    orderPositionInfo.setQsInfo(qsDto);
+
+                    PositionDto qsPosition = new PositionDto();
+                    riderPositions.stream().filter(riderPosition -> riderPosition.getRiderId().equals(posOrder.getQsId())).findFirst().ifPresent(rPosition -> {
+                        qsPosition.setLat(rPosition.getLatitude().toString());
+                        qsPosition.setLng(rPosition.getLongitude().toString());
+                    });
+                    orderPositionInfo.setQsPosition(qsPosition);
+                }
+                PositionDto mdPosition = new PositionDto();
+                stores.stream().filter(posStore -> posStore.getId().equals(Integer.valueOf(posOrder.getMdId().toString()))).findFirst().ifPresent(p -> {
+                    mdPosition.setLat(p.getLatitude().toString());
+                    mdPosition.setLng(p.getLongitude().toString());
+                });
+                orderPositionInfo.setMdPosition(mdPosition);
+
+                Map map = JSON.parseObject(posOrder.getShAddress(), Map.class);
+                PositionDto userPosition = new PositionDto();
+                userPosition.setLat(map.get("latitude").toString());
+                userPosition.setLng(map.get("longitude").toString());
+                orderPositionInfo.setUserPosition(userPosition);
+
+                result.add(orderPositionInfo);
+            }
+        }
+
+        return AjaxResult.success(result);
+    }
+
+
+}

+ 212 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderRatingController.java

@@ -0,0 +1,212 @@
+package com.ruoyi.app.order;
+
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.domain.PointsTransaction;
+import com.ruoyi.system.domain.SysPointControl;
+import com.ruoyi.system.domain.UserWallet;
+import com.ruoyi.system.service.IPointsTransactionService;
+import com.ruoyi.system.service.ISysPointControlService;
+import com.ruoyi.system.service.IUserWalletService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.PosOrderRating;
+import com.ruoyi.system.service.IPosOrderRatingService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 订单评级Controller
+ *
+ * @author ruoyi
+ * @date 2025-07-29
+ */
+@RestController
+@RequestMapping("/system/rating")
+public class PosOrderRatingController extends BaseController
+{
+    @Autowired
+    private IPosOrderRatingService posOrderRatingService;
+    @Autowired
+    private ISysPointControlService pointControlService;
+    @Autowired
+    private IUserWalletService userWalletService;
+    @Autowired
+    private IPointsTransactionService pointsTransactionService;
+
+
+    /**
+     * 消费用户保存订单评级
+     * @param posOrderRating
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @PostMapping("/saveOrderRating")
+    public AjaxResult saveOrderRating(
+            @RequestHeader String token,
+            @RequestBody PosOrderRating posOrderRating) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        PosOrderRating review = posOrderRatingService.getOne(new LambdaQueryWrapper<PosOrderRating>().eq(PosOrderRating::getDdId, posOrderRating.getDdId()));
+        if(review != null) {
+            toAjax(posOrderRatingService.updatePosOrderRating(posOrderRating));
+        }
+        posOrderRating.setUserId(Long.valueOf(id));
+        posOrderRating.setCreateTime(DateUtils.getNowDate());
+        //两个星级都设置才能获取积分
+        if(posOrderRating.getMdStars()!=null && posOrderRating.getMdStars()>0 && posOrderRating.getQsStars()!=null && posOrderRating.getQsStars()>0){
+            addPoint(Long.valueOf(id),posOrderRating.getDdId());
+        }
+
+        return toAjax(posOrderRatingService.insertPosOrderRating(posOrderRating));
+    }
+    /**
+     * 添加积分
+     */
+    private void addPoint(Long userid, Long ddId){
+        SysPointControl control = pointControlService.getById(1);
+        //开启评论获得积分
+        if(control.getReviewEnable().equals(1L)){
+            LambdaQueryWrapper<UserWallet> walletQuery=new LambdaQueryWrapper<>();
+            walletQuery.eq(UserWallet::getUserId,userid);
+            UserWallet userWallet = userWalletService.getOne(walletQuery);
+
+            if(userWallet==null){
+                userWallet=new UserWallet();
+                userWallet.setUserId(userid);
+                userWallet.setPointsWallet(control.getReviewPoints());
+                createPointTransaction(userid,control.getReviewPoints(),userWallet.getPointsWallet(),ddId);
+                userWalletService.save(userWallet);
+            }else{
+                Long userPoint = userWallet.getPointsWallet();
+                Long point = control.getReviewPoints();
+                Long newPoint = userPoint+point;
+                userWallet.setPointsWallet(newPoint);
+                int oldVersion = userWallet.getVersion();
+                userWallet.setVersion(userWallet.getVersion()+1);
+                walletQuery.eq(UserWallet::getVersion,oldVersion);
+                boolean update= userWalletService.update(userWallet,walletQuery);
+                if(!update){
+                    throw new ServiceException(MessageUtils.message("no.points.update.fail"));
+                }
+                createPointTransaction(userid,control.getReviewPoints(),userWallet.getPointsWallet(),ddId);
+            }
+
+        }
+
+    }
+    /**
+     * 创建积分流水
+     */
+    private void createPointTransaction(Long userid,Long pointsChange,Long currentPoints,Long ddId){
+        PointsTransaction pointsTransaction = new PointsTransaction();
+        pointsTransaction.setUserId(userid);
+        pointsTransaction.setPointsChange("+"+pointsChange);
+        pointsTransaction.setCurrentPoints(currentPoints.toString());
+        pointsTransaction.setType("0");
+        pointsTransaction.setDdId(ddId);
+        pointsTransaction.setCreateTime(new Date());
+        pointsTransactionService.save(pointsTransaction);
+    }
+
+
+
+    /**
+     * 获取订单评级
+     * @return
+     */
+    @Auth
+    @GetMapping("/getOrderRating")
+    public AjaxResult getOrderRating(
+            @RequestHeader String token,
+            @RequestParam String ddId) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        PosOrderRating rating = posOrderRatingService.getOne(new LambdaQueryWrapper<PosOrderRating>().eq(PosOrderRating::getDdId, ddId));
+        return success(rating);
+    }
+
+
+    /**
+     * 查询订单评级列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:rating:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosOrderRating posOrderRating)
+    {
+        startPage();
+        List<PosOrderRating> list = posOrderRatingService.selectPosOrderRatingList(posOrderRating);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出订单评级列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:rating:export')")
+    @Log(title = "订单评级", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosOrderRating posOrderRating)
+    {
+        List<PosOrderRating> list = posOrderRatingService.selectPosOrderRatingList(posOrderRating);
+        ExcelUtil<PosOrderRating> util = new ExcelUtil<PosOrderRating>(PosOrderRating.class);
+        util.exportExcel(response, list, "订单评级数据");
+    }
+
+    /**
+     * 获取订单评级详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:rating:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posOrderRatingService.selectPosOrderRatingById(id));
+    }
+
+    /**
+     * 新增订单评级
+     */
+    @PreAuthorize("@ss.hasPermi('system:rating:add')")
+    @Log(title = "订单评级", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosOrderRating posOrderRating)
+    {
+        return toAjax(posOrderRatingService.insertPosOrderRating(posOrderRating));
+    }
+
+    /**
+     * 修改订单评级
+     */
+    @PreAuthorize("@ss.hasPermi('system:rating:edit')")
+    @Log(title = "订单评级", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosOrderRating posOrderRating)
+    {
+        return toAjax(posOrderRatingService.updatePosOrderRating(posOrderRating));
+    }
+
+    /**
+     * 删除订单评级
+     */
+    @PreAuthorize("@ss.hasPermi('system:rating:remove')")
+    @Log(title = "订单评级", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posOrderRatingService.deletePosOrderRatingByIds(ids));
+    }
+}

+ 231 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosReviewController.java

@@ -0,0 +1,231 @@
+package com.ruoyi.app.order;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.system.domain.PointsTransaction;
+import com.ruoyi.system.domain.SysPointControl;
+import com.ruoyi.system.domain.UserWallet;
+import com.ruoyi.system.mapper.PosReviewMapper;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.PosReview;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * reviewController
+ *
+ * @author ruoyi
+ * @date 2023-06-08
+ */
+@RestController
+@RequestMapping("/system/review")
+public class PosReviewController extends BaseController
+{
+    @Autowired
+    private IPosReviewService posReviewService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private PosReviewMapper posReviewMapper;
+
+    @Autowired
+    private ISysPointControlService pointControlService;
+    @Autowired
+    private IUserWalletService userWalletService;
+    @Autowired
+    private IPointsTransactionService  pointsTransactionService;
+
+    @Anonymous
+    @GetMapping("/getmdrevew")
+    public AjaxResult getmdrevew(@RequestParam Integer page,
+                                 @RequestParam Integer size,
+                                 @RequestParam Long mdid){
+        IPage<PosReview> palist = new Page<>(page,size);
+        QueryWrapper<PosReview> Wrapper= new QueryWrapper<>();
+        Wrapper.eq("md_id",mdid);
+        IPage<PosReview> list =  posReviewService.page(palist,Wrapper);
+        List<PosReview> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        for(int i=0;i<orlist.size();i++){
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id",orlist.get(i).getId());
+            org.put("ddId",orlist.get(i).getDdId());
+            org.put("score",orlist.get(i).getScore());
+            org.put("cretim",sdf.format(orlist.get(i).getCretim()));
+            org.put("content",orlist.get(i).getContent());
+            org.put("images",orlist.get(i).getImages());
+            org.put("user",orlist.get(i).getAnonymous()==0?infoUserService.getById(orlist.get(i).getUserId()):"匿名");
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Anonymous
+    @Auth
+    @PostMapping("/addrevew")
+    public AjaxResult addrevew(@RequestHeader String token,@RequestBody PosReview posReview)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        PosReview review = posReviewMapper.getrewiew(posReview.getDdId());
+        if(review==null){
+            posReview.setUserId(Long.valueOf(id));
+            //判断是否为新增
+            if(ObjectUtil.isEmpty(posReview.getId())){
+                addPoint(Long.valueOf(id),posReview.getDdId());
+            }
+            boolean org = posReviewService.saveOrUpdate(posReview);
+            if(org){
+                return success(MessageUtils.message("no.comment.success"));
+            }else {
+                throw new ServiceException(MessageUtils.message("no.comment.fail"));
+            }
+        }else {
+            return error(MessageUtils.message("no.comment.repeat"));
+        }
+    }
+    /**
+     * 添加积分
+     */
+    private void addPoint(Long userid, Long ddId){
+        SysPointControl control = pointControlService.getById(1);
+        //开启评论获得积分
+        if(control.getReviewEnable().equals(1L)){
+            LambdaQueryWrapper<UserWallet> walletQuery=new LambdaQueryWrapper<>();
+            walletQuery.eq(UserWallet::getUserId,userid);
+            UserWallet userWallet = userWalletService.getOne(walletQuery);
+
+            if(userWallet==null){
+                userWallet=new UserWallet();
+                userWallet.setUserId(userid);
+                userWallet.setPointsWallet(control.getReviewPoints());
+                createPointTransaction(userid,control.getReviewPoints(),userWallet.getPointsWallet(),ddId);
+                userWalletService.save(userWallet);
+            }else{
+                Long userPoint = userWallet.getPointsWallet();
+                Long point = control.getReviewPoints();
+                Long newPoint = userPoint+point;
+                userWallet.setPointsWallet(newPoint);
+                int oldVersion = userWallet.getVersion();
+                userWallet.setVersion(userWallet.getVersion()+1);
+                walletQuery.eq(UserWallet::getVersion,oldVersion);
+               boolean update= userWalletService.update(userWallet,walletQuery);
+               if(!update){
+                   throw new ServiceException(MessageUtils.message("no.points.update.fail"));
+               }
+                createPointTransaction(userid,control.getReviewPoints(),userWallet.getPointsWallet(),ddId);
+            }
+
+        }
+
+    }
+    /**
+     * 创建积分流水
+     */
+    private void createPointTransaction(Long userid,Long pointsChange,Long currentPoints,Long ddId){
+        PointsTransaction pointsTransaction = new PointsTransaction();
+        pointsTransaction.setUserId(userid);
+        pointsTransaction.setPointsChange("+"+pointsChange);
+        pointsTransaction.setCurrentPoints(currentPoints.toString());
+        pointsTransaction.setType("0");
+        pointsTransaction.setDdId(ddId);
+        pointsTransaction.setCreateTime(new Date());
+        pointsTransactionService.save(pointsTransaction);
+    }
+
+
+
+
+    /**
+     * 查询review列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:review:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosReview posReview)
+    {
+        startPage();
+        List<PosReview> list = posReviewService.selectPosReviewList(posReview);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出review列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:review:export')")
+    @Log(title = "review", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosReview posReview)
+    {
+        List<PosReview> list = posReviewService.selectPosReviewList(posReview);
+        ExcelUtil<PosReview> util = new ExcelUtil<PosReview>(PosReview.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.review"));
+    }
+
+    /**
+     * 获取review详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:review:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posReviewService.selectPosReviewById(id));
+    }
+
+    /**
+     * 新增review
+     */
+    @PreAuthorize("@ss.hasPermi('system:review:add')")
+    @Log(title = "review", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosReview posReview)
+    {
+        return toAjax(posReviewService.insertPosReview(posReview));
+    }
+
+    /**
+     * 修改review
+     */
+    @PreAuthorize("@ss.hasPermi('system:review:edit')")
+    @Log(title = "review", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosReview posReview)
+    {
+        return toAjax(posReviewService.updatePosReview(posReview));
+    }
+
+    /**
+     * 删除review
+     */
+    @PreAuthorize("@ss.hasPermi('system:review:remove')")
+    @Log(title = "review", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posReviewService.deletePosReviewByIds(ids));
+    }
+}

+ 304 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/TaxiOrderController.java

@@ -0,0 +1,304 @@
+package com.ruoyi.app.order;
+
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.RiderPosition;
+import com.ruoyi.system.mapper.TaxiOrderMapper;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.service.IRiderPositionService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import io.swagger.models.auth.In;
+import lombok.SneakyThrows;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.TaxiOrder;
+import com.ruoyi.system.service.ITaxiOrderService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * TaxiOrderController
+ * 
+ * @author ruoyi
+ * @date 2024-01-26
+ */
+@RestController
+@RequestMapping("/system/txorder")
+public class TaxiOrderController extends BaseController
+{
+    @Autowired
+    private ITaxiOrderService taxiOrderService;
+    @Autowired
+    private TaxiOrderMapper taxiOrderMapper;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IRiderPositionService riderPositionService;
+
+    //获取订单详情
+    @Anonymous
+    @GetMapping("/getTxorder")
+    public AjaxResult getTxorder(@RequestParam Long  id)
+    {
+        TaxiOrder order =  taxiOrderService.getById(id);
+        JSONObject org = new JSONObject();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        org.put("id",order.getId());
+        org.put("ddId",order.getDdId());
+        org.put("user",infoUserService.getById(order.getUserId()));
+        org.put("driver",infoUserService.getById(order.getDriverId()));
+        org.put("boardingAddress",order.getBoardingAddress());
+        org.put("intoLongitude",order.getIntoLongitude());
+        org.put("intoLatitude",order.getIntoLatitude());
+        org.put("downAddress",order.getDownAddress());
+        org.put("downLongitude",order.getDownLongitude());
+        org.put("downLatitude",order.getIntoLatitude());
+        org.put("distance",order.getDistance());
+        org.put("state",order.getState());
+        org.put("taxiType",order.getTaxiType());
+        org.put("releaseId",order.getReleaseId());
+        org.put("orderTime",sdf.format(order.getOrderTime()));
+        org.put("boardingTime",order.getBoardingTime());
+        org.put("alightingTime",order.getAlightingTime());
+        org.put("appointmentTime",order.getAppointmentTime());
+        org.put("fare",order.getFare());
+        org.put("highwayCosts",order.getHighwayCosts());
+        org.put("amount",order.getAmount());
+        org.put("estimatedDuration",order.getEstimatedDuration());
+        org.put("notes",order.getNotes());
+        org.put("coupon",order.getCoupon());
+        QueryWrapper<RiderPosition> query= new QueryWrapper<>();
+        query.eq("rider_id",order.getDriverId());
+        org.put("RiderPosition",order.getDriverId()==null||order.getDriverId().equals("")?null:riderPositionService.getOne(query));
+
+        return success(org);
+    }
+    //获取用户订单
+    @Anonymous
+    @Auth
+    @GetMapping("/getUsTxorder")
+    public AjaxResult getUsTxorder(@RequestHeader String token,
+                                   @RequestParam Integer page,
+                                   @RequestParam Integer size,
+                                   @RequestParam String type,
+                                   @RequestParam(defaultValue = "") String state)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        IPage<TaxiOrder> palist = new Page<>(page, size);
+        QueryWrapper<TaxiOrder> queryWrapper= new QueryWrapper<>();
+        queryWrapper.select().orderByDesc("order_time");
+        if(type.equals("0")){
+            queryWrapper.eq("user_id",id);
+        }else {
+            queryWrapper.eq("driver_id",id);
+        }
+        if(!"".equals(state)){
+            queryWrapper.eq("state",state);
+        }
+        IPage<TaxiOrder> list =  taxiOrderService.page(palist,queryWrapper);
+        List<TaxiOrder> orlist = list.getRecords();
+        JSONArray arr = new JSONArray();
+        for(int i=0;i<orlist.size();i++){
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id",orlist.get(i).getId());
+            org.put("ddId",orlist.get(i).getDdId());
+            org.put("user",infoUserService.getById(orlist.get(i).getUserId()));
+            org.put("driver",infoUserService.getById(orlist.get(i).getDriverId()));
+            org.put("boardingAddress",orlist.get(i).getBoardingAddress());
+            org.put("intoLongitude",orlist.get(i).getIntoLongitude());
+            org.put("intoLatitude",orlist.get(i).getIntoLatitude());
+            org.put("downAddress",orlist.get(i).getDownAddress());
+            org.put("downLongitude",orlist.get(i).getDownLongitude());
+            org.put("downLatitude",orlist.get(i).getIntoLatitude());
+            org.put("distance",orlist.get(i).getDistance());
+            org.put("state",orlist.get(i).getState());
+            org.put("taxiType",orlist.get(i).getTaxiType());
+            org.put("releaseId",orlist.get(i).getReleaseId());
+            org.put("orderTime",sdf.format(orlist.get(i).getOrderTime()));
+            org.put("boardingTime",orlist.get(i).getBoardingTime());
+            org.put("alightingTime",orlist.get(i).getAlightingTime());
+            org.put("appointmentTime",orlist.get(i).getAppointmentTime());
+            org.put("fare",orlist.get(i).getFare());
+            org.put("highwayCosts",orlist.get(i).getHighwayCosts());
+            org.put("amount",orlist.get(i).getAmount());
+            org.put("estimatedDuration",orlist.get(i).getEstimatedDuration());
+            org.put("notes",orlist.get(i).getNotes());
+            org.put("coupon",orlist.get(i).getCoupon());
+            arr.add(org);
+        }
+        return success(arr);
+    }
+
+    //获取附近可接订单
+    @Anonymous
+    @GetMapping("/getFjorder")
+    public AjaxResult getFjorder(@RequestParam BigDecimal longitude,
+                                 @RequestParam BigDecimal latitude,
+                                 @RequestParam Integer page,
+                                 @RequestParam Integer juli)
+    {
+        List<TaxiOrder> list = taxiOrderMapper.getfjorder(longitude,latitude,(page-1)*20,juli);
+        JSONArray arr = new JSONArray();
+        for(int i=0;i<list.size();i++){
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id",list.get(i).getId());
+            org.put("ddId",list.get(i).getDdId());
+            org.put("user",infoUserService.getById(list.get(i).getUserId()));
+            org.put("driver",infoUserService.getById(list.get(i).getDriverId()));
+            org.put("boardingAddress",list.get(i).getBoardingAddress());
+            org.put("intoLongitude",list.get(i).getIntoLongitude());
+            org.put("intoLatitude",list.get(i).getIntoLatitude());
+            org.put("downAddress",list.get(i).getDownAddress());
+            org.put("downLongitude",list.get(i).getDownLongitude());
+            org.put("downLatitude",list.get(i).getIntoLatitude());
+            org.put("distance",list.get(i).getDistance());
+            org.put("state",list.get(i).getState());
+            org.put("taxiType",list.get(i).getTaxiType());
+            org.put("releaseId",list.get(i).getReleaseId());
+            org.put("orderTime",sdf.format(list.get(i).getOrderTime()));
+            org.put("boardingTime",list.get(i).getBoardingTime());
+            org.put("alightingTime",list.get(i).getAlightingTime());
+            org.put("appointmentTime",list.get(i).getAppointmentTime());
+            org.put("fare",list.get(i).getFare());
+            org.put("highwayCosts",list.get(i).getHighwayCosts());
+            org.put("amount",list.get(i).getAmount());
+            org.put("estimatedDuration",list.get(i).getEstimatedDuration());
+            org.put("notes",list.get(i).getNotes());
+            org.put("coupon",list.get(i).getCoupon());
+            arr.add(org);
+        }
+        return success(MessageUtils.message("no.obtained.success"), arr);
+
+    }
+
+    //修改订单
+    @Anonymous
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PostMapping("/SetTxorder")
+    public AjaxResult SetTxorder(@RequestBody TaxiOrder taxiOrder)
+    {
+        TaxiOrder order = taxiOrderService.getById(taxiOrder.getId());
+        if(order==null){
+            return error(MessageUtils.message("no.order.not.exist"));
+        }else {
+            boolean org = taxiOrderService.saveOrUpdate(taxiOrder);
+            if(org){
+                return success(MessageUtils.message("no.modify.success"));
+            }else {
+                return error();
+            }
+        }
+
+    }
+
+    //新增订单
+    @SneakyThrows
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PostMapping("/addTxorder")
+    public AjaxResult addTxorder(@RequestHeader String token ,@RequestBody TaxiOrder taxiOrder)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        DateUtil date = new DateUtil();
+        taxiOrder.setUserId(Long.valueOf(id));
+        taxiOrder.setReleaseId(Long.valueOf(id));
+        taxiOrder.setDdId(date.getTimeMillis());
+        int org = taxiOrderService.insertTaxiOrder(taxiOrder);
+        if(org==1){
+            return success(MessageUtils.message("no.order.place.success"), taxiOrder);
+        }else {
+            return error();
+        }
+    }
+    /**
+     * 查询TaxiOrder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:txorder:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TaxiOrder taxiOrder)
+    {
+        startPage();
+        List<TaxiOrder> list = taxiOrderService.selectTaxiOrderList(taxiOrder);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出TaxiOrder列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:txorder:export')")
+    @Log(title = "TaxiOrder", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, TaxiOrder taxiOrder)
+    {
+        List<TaxiOrder> list = taxiOrderService.selectTaxiOrderList(taxiOrder);
+        ExcelUtil<TaxiOrder> util = new ExcelUtil<TaxiOrder>(TaxiOrder.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.taxiorder"));
+    }
+
+    /**
+     * 获取TaxiOrder详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:txorder:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(taxiOrderService.selectTaxiOrderById(id));
+    }
+
+    /**
+     * 新增TaxiOrder
+     */
+    @PreAuthorize("@ss.hasPermi('system:txorder:add')")
+    @Log(title = "TaxiOrder", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TaxiOrder taxiOrder)
+    {
+        return toAjax(taxiOrderService.insertTaxiOrder(taxiOrder));
+    }
+
+    /**
+     * 修改TaxiOrder
+     */
+    @PreAuthorize("@ss.hasPermi('system:txorder:edit')")
+    @Log(title = "TaxiOrder", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TaxiOrder taxiOrder)
+    {
+        return toAjax(taxiOrderService.updateTaxiOrder(taxiOrder));
+    }
+
+    /**
+     * 删除TaxiOrder
+     */
+    @PreAuthorize("@ss.hasPermi('system:txorder:remove')")
+    @Log(title = "TaxiOrder", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(taxiOrderService.deleteTaxiOrderByIds(ids));
+    }
+}

+ 140 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/TaxiPricesController.java

@@ -0,0 +1,140 @@
+package com.ruoyi.app.order;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.utils.GetJvli;
+import com.ruoyi.app.utils.RsaMima;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.domain.InfoUser;
+import com.ruoyi.system.domain.vo.UserDTO;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.TaxiPrices;
+import com.ruoyi.system.service.ITaxiPricesService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * TaxiPricesController
+ * 
+ * @author ruoyi
+ * @date 2024-01-26
+ */
+@RestController
+@RequestMapping("/system/txprices")
+public class TaxiPricesController extends BaseController
+{
+    @Autowired
+    private ITaxiPricesService taxiPricesService;
+
+
+    @Anonymous
+    @GetMapping("/getTaxiPrices")
+    public AjaxResult getTaxiPrices() {
+        TaxiPrices prices = taxiPricesService.getById(1);
+        return success(prices);
+    }
+    //订算运费
+    @Anonymous
+    @GetMapping("/ganyunfei")
+    public AjaxResult ganyunfei(@RequestParam double lat1,
+                                @RequestParam double lng1,
+                                @RequestParam double lat2,
+                                @RequestParam double lng2) {
+        GetJvli getjvli = new GetJvli();
+        TaxiPrices prices = taxiPricesService.getById(1);
+        JSONObject bje = new JSONObject();
+        DecimalFormat df = new DecimalFormat("#.0");
+        Double jvli = getjvli.getDistance(lat1,lng1,lat2,lng2);
+        Double yunjia = Double.valueOf(0);
+        Double jjjvli = jvli-prices.getStartingDistance();
+        Double jlyunj = jjjvli*prices.getSkipPrice();
+        if(jvli>=prices.getStartingDistance()){
+            yunjia = prices.getStartingPrice()+jlyunj;
+        }else {
+            yunjia = prices.getStartingPrice();
+        }
+        bje.put("jvli",df.format(jvli));
+        bje.put("freight",df.format(yunjia));
+        return success(bje);
+    }
+    /**
+     * 查询TaxiPrices列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:txprices:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TaxiPrices taxiPrices)
+    {
+        startPage();
+        List<TaxiPrices> list = taxiPricesService.selectTaxiPricesList(taxiPrices);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出TaxiPrices列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:txprices:export')")
+    @Log(title = "TaxiPrices", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, TaxiPrices taxiPrices)
+    {
+        List<TaxiPrices> list = taxiPricesService.selectTaxiPricesList(taxiPrices);
+        ExcelUtil<TaxiPrices> util = new ExcelUtil<TaxiPrices>(TaxiPrices.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.taxiprices"));
+    }
+
+    /**
+     * 获取TaxiPrices详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:txprices:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(taxiPricesService.selectTaxiPricesById(id));
+    }
+
+    /**
+     * 新增TaxiPrices
+     */
+    @PreAuthorize("@ss.hasPermi('system:txprices:add')")
+    @Log(title = "TaxiPrices", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TaxiPrices taxiPrices)
+    {
+        return toAjax(taxiPricesService.insertTaxiPrices(taxiPrices));
+    }
+
+    /**
+     * 修改TaxiPrices
+     */
+    @PreAuthorize("@ss.hasPermi('system:txprices:edit')")
+    @Log(title = "TaxiPrices", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TaxiPrices taxiPrices)
+    {
+        return toAjax(taxiPricesService.updateTaxiPrices(taxiPrices));
+    }
+
+    /**
+     * 删除TaxiPrices
+     */
+    @PreAuthorize("@ss.hasPermi('system:txprices:remove')")
+    @Log(title = "TaxiPrices", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(taxiPricesService.deleteTaxiPricesByIds(ids));
+    }
+}

+ 128 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/TestTask.java

@@ -0,0 +1,128 @@
+package com.ruoyi.app.order;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.utils.zaloPay.ZaloPay;
+import com.ruoyi.app.utils.zaloPay.ZaloPayConfig;
+import com.ruoyi.app.utils.zaloPay.ZaloPayProperties;
+import com.ruoyi.app.utils.zaloPay.ZaloPayQueryRefundResponse;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.PoseOrderZalopay;
+import com.ruoyi.system.domain.UserBilling;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.mapper.UserBillingMapper;
+import com.ruoyi.system.service.IPosOrderService;
+import com.ruoyi.system.service.IPoseOrderZalopayService;
+import com.ruoyi.system.service.IUserBillingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+
+/**
+ * 任务调度
+ */
+@Component("testTask")
+public class TestTask {
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private PosOrderMapper posOrderMapper;
+    @Autowired
+    private IUserBillingService userBillingService;
+    @Autowired
+    private UserBillingMapper userBillingMapper;
+    @Autowired
+    private PosOrderController posorder;
+    @Autowired
+    private IPoseOrderZalopayService zalopayService;
+    @Autowired
+    private ZaloPayConfig zaloPayConfig;
+    @Autowired
+    private ZaloPay zaloPay;
+
+
+    private static Logger logger = LoggerFactory.getLogger(TestTask.class);
+
+    /**
+     * 订单未支付,超过一定时间后取消
+     * @param minute
+     */
+    public void testTiming(Integer minute){
+        System.out.println("间隔时间:"+minute+"分钟");
+        List<PosOrder> ordlist = posOrderMapper.getOrderTim(0,minute);
+        for(int i=0;i<ordlist.size();i++){
+            PosOrder posOrder = new PosOrder();
+            posOrder.setId(ordlist.get(i).getId());
+            posOrder.setState(10L);
+            posOrderService.saveOrUpdate(posOrder);
+            try {
+                if(posOrder.getPoints()!=null && posOrder.getPoints()>0){
+                    posorder.returnPoints(posOrder.getUserId(),Long.valueOf(posOrder.getPoints()),posOrder.getDdId());
+                }
+            }catch (Exception e){
+                logger.warn("定时任务取消订单,积分返还失败订单号: {},异常信息:{}", posOrder.getId(),e.getMessage());
+            }
+        }
+        List<UserBilling> ublist = userBillingMapper.getbillingTim(minute);
+        for(int i=0;i<ublist.size();i++){
+            UserBilling userBilling = new UserBilling();
+            userBilling.setId(ublist.get(i).getId());
+            userBilling.setState("2");
+            userBillingService.saveOrUpdate(userBilling);
+        }
+    }
+
+    /**
+     * 退款处理中,查询zalopay退款结果,设置退款状态
+     */
+   public void refundProcessing() throws URISyntaxException, IOException {
+        LambdaQueryWrapper<PosOrder> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PosOrder::getState,13L); //13退款处理中
+        List<PosOrder> list = posOrderMapper.selectList(queryWrapper);
+        System.out.println("定时任务查询退款处理中的数据,数量: "+list.size());
+       logger.info("定时任务查询退款处理中的数据,数量: {}", list.size());
+        for(int i=0;i<list.size();i++){
+            PoseOrderZalopay zaloResopen = zalopayService.getOne(new QueryWrapper<PoseOrderZalopay>().eq("dd_id", list.get(i).getDdId()));
+            if(zaloResopen==null){
+                System.out.println("定时任务查询退款结果,未查到支付信息订单号: "+list.get(i).getDdId());
+                logger.warn("定时任务查询退款结果,未查到支付信息订单号: {}", list.get(i).getDdId());
+                break;
+            }
+            String mRefundId = zaloResopen.getMRefundId();
+            ZaloPayProperties.ZaloPayConfig config = zaloPayConfig.getZaloPayConfig(zaloResopen.getPayType());
+            ZaloPayQueryRefundResponse response = zaloPay.queryRefundStatus(mRefundId,config);
+            if(response.getReturnCode()==1){
+                System.out.println("定时任务处理退款结果,订单号: "+list.get(i).getDdId());
+                logger.warn("定时任务处理退款结果,订单号: {}", list.get(i).getDdId());
+                PosOrder posOrder = new PosOrder();
+                posOrder.setId(list.get(i).getId());
+                posOrder.setState(11L); //11售后完成
+                posOrderService.saveOrUpdate(posOrder);
+            }
+        }
+
+    }
+
+    /**
+     * 订单送达,超过一定时间后自动设置为完成
+     * @param minute
+     */
+    public void zidwancheng(Integer minute){
+        System.out.println("间隔时间:"+minute+"分钟");
+        List<PosOrder> ordlist = posOrderMapper.getOverOrderTim(60,minute);
+        for(int i=0;i<ordlist.size();i++){
+            PosOrder pos = new PosOrder();
+            pos.setId(ordlist.get(i).getId());
+            pos.setState(5L);
+            posOrderService.saveOrUpdate(pos);
+            PosOrder order = posOrderService.getById(ordlist.get(i).getId());
+            posorder.setSanghuBilling(order);
+            posorder.setQishouBilling(order);
+        }
+    }
+}

+ 55 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/ZaloPayCommonService.java

@@ -0,0 +1,55 @@
+package com.ruoyi.app.order;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.PoseOrderZalopay;
+import com.ruoyi.system.service.IPoseOrderZalopayService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/*
+ * ZaloPay通用方法
+ * @Description:
+ */
+@Component
+public class ZaloPayCommonService {
+
+    @Autowired
+    private IPoseOrderZalopayService zalopayService;
+    /**
+     *  记录ZaloPay支付信息
+     */
+
+    public void setZaloPayOrder(String ddId,String createResponse,String callbackResponse,String refundResponse,String mRefundId,String payType) {
+        PoseOrderZalopay poseOrderZalopay =zalopayService.getOne(new QueryWrapper<PoseOrderZalopay>().eq("dd_id", ddId));
+        PoseOrderZalopay zaloResopen = new PoseOrderZalopay();
+        if(StringUtils.isNotEmpty(createResponse)){
+            zaloResopen.setCreateResponse(createResponse);
+            zaloResopen.setCreateResponseTime(new Date());
+        }
+        if(StringUtils.isNotEmpty(callbackResponse)){
+            zaloResopen.setCallbackResponse(callbackResponse);
+            zaloResopen.setCallbackResponseTime(new Date());
+        }
+        if(StringUtils.isNotEmpty(refundResponse)){
+            zaloResopen.setRefundResponse(refundResponse);
+            zaloResopen.setRefundResponseTime(new Date());
+        }
+        if(StringUtils.isNotEmpty(mRefundId)){
+            zaloResopen.setMRefundId(mRefundId);
+        }
+        if(StringUtils.isNotEmpty(payType)){
+            zaloResopen.setPayType(payType);
+        }
+        if(poseOrderZalopay==null){
+            zaloResopen.setDdId(ddId);
+            zalopayService.save(zaloResopen);
+        }else{
+            zaloResopen.setId(poseOrderZalopay.getId());
+            zalopayService.updateById(zaloResopen);
+        }
+    }
+
+}

+ 60 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/OrderPositionInfo.java

@@ -0,0 +1,60 @@
+package com.ruoyi.app.order.dto;
+
+import com.ruoyi.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class OrderPositionInfo {
+
+    /**
+     * 订单号
+     */
+    public Long ddId;
+
+    /**
+     * 配送时间
+     */
+    private String delryTime;
+    /**
+     * 预计送达时间
+     */
+    private String yjsdTime;
+
+    /**
+     * 订单状态
+     */
+
+    public Long orderState;
+
+
+
+    /** 出餐状态*/
+    private Long diningStatus;
+
+    /** 支付类型:1 货到付款 2 vnpay 3 zalopay */
+    private String payType;
+    /**
+     * 骑手位置
+     */
+    public PositionDto QsPosition;
+
+    /**
+     * 商家位置
+     */
+    public PositionDto mdPosition;
+
+    /**
+     * 用户位置
+     */
+
+    public PositionDto userPosition;
+
+    /**
+     * 配送时间
+     */
+    public QsDto qsInfo;
+
+
+}
+
+

+ 77 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/OrderPushBodyDto.java

@@ -0,0 +1,77 @@
+package com.ruoyi.app.order.dto;
+
+import cn.hutool.core.lang.TypeReference;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class OrderPushBodyDto {
+    private String ddId;
+    private String state;
+    //0:语音提醒新订单
+    private int type=-1;
+    //1 外卖订单 2 充值订单
+    private int pushType=1;
+
+    private String title;
+    private String content;
+
+
+    public OrderPushBodyDto(String title, String content, String ddId, String state, int type,int pushType) {
+       this.title = title;
+        this.content = content;
+        this.ddId = ddId;
+        this.state = state;
+        this.type = type;
+        this.pushType=pushType;
+    }
+
+    public OrderPushBodyDto(String ddId, String state, int type) {
+        this.ddId = ddId;
+        this.state = state;
+        this.type = type;
+    }
+
+    public OrderPushBodyDto(String ddId, String state, int type,int pushType) {
+        this.ddId = ddId;
+        this.state = state;
+        this.type = type;
+        this.pushType=pushType;
+    }
+
+    public OrderPushBodyDto(String ddId, String state) {
+        this.ddId = ddId;
+        this.state = state;
+        // type将使用类字段定义时的默认值-1
+    }
+
+    public static String getJson(String ddId, String state) {
+        OrderPushBodyDto orderPushBodyDto = new OrderPushBodyDto(ddId, state);
+        return JSONObject.toJSONString(orderPushBodyDto);
+    }
+
+    public static String getJson(String ddId, String state, int type) {
+        OrderPushBodyDto orderPushBodyDto = new OrderPushBodyDto(ddId, state, type);
+        return JSONObject.toJSONString(orderPushBodyDto);
+    }
+
+    public static String getJson(String ddId, String state, int type,int pushType) {
+        OrderPushBodyDto orderPushBodyDto = new OrderPushBodyDto(ddId, state, type,pushType);
+        return JSONObject.toJSONString(orderPushBodyDto);
+    }
+
+
+    public static Map<String, Object> getMap(String ddId, String state, int type,int pushType) {
+        OrderPushBodyDto orderPushBodyDto = new OrderPushBodyDto(ddId, state, type,pushType);
+        return JSON.parseObject(JSON.toJSONString(orderPushBodyDto), new TypeReference<Map<String, Object>>() {
+        });
+    }
+
+    public static String margeMapGetJsonString(Map<String, Object> map1, Map<String, Object> map2){
+        map1.putAll(map2);
+        return JSON.toJSONString(map1);
+    }
+}

+ 20 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/PositionDto.java

@@ -0,0 +1,20 @@
+package com.ruoyi.app.order.dto;
+
+import lombok.Data;
+
+/**
+ * @Description: 位置信息
+ * @Author: Liyi
+ * @Date: 2022/1/20
+ **/
+@Data
+public class PositionDto {
+    /**
+     * 经度
+     */
+    public String lng;
+    /**
+     * 纬度
+     */
+    public String lat;
+}

+ 21 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/QsDto.java

@@ -0,0 +1,21 @@
+package com.ruoyi.app.order.dto;
+
+import lombok.Data;
+
+@Data
+public class QsDto {
+    /**
+     * 骑手名称
+     */
+    public String userName;
+    /**
+     * 骑手昵称
+     */
+
+    public String nickName;
+
+    /**
+     * 配送时间
+     */
+    public String delryTime;
+}

+ 142 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/BankCardController.java

@@ -0,0 +1,142 @@
+package com.ruoyi.app.pay;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.domain.InfoUser;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.BankCard;
+import com.ruoyi.system.service.IBankCardService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * BankCardController
+ * 
+ * @author ruoyi
+ * @date 2023-08-06
+ */
+@RestController
+@RequestMapping("/system/card")
+public class BankCardController extends BaseController
+{
+    @Autowired
+    private IBankCardService bankCardService;
+
+
+    //删除银行卡
+    @Anonymous
+    @Auth
+    @GetMapping("/delebankcard")
+    public AjaxResult delebankcard(@RequestParam Long id)
+    {
+        int org = bankCardService.deleteBankCardById(id);
+        if(org==1){
+            return success(MessageUtils.message("no.delete.success"));
+        }else {
+            return error(MessageUtils.message("no.delete.fail"));
+        }
+    }
+    //用户银行卡列表
+    @Anonymous
+    @Auth
+    @GetMapping("/getbankcard")
+    public AjaxResult getbankcard(@RequestHeader String token)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String userid = jwtUtil.getusid(token);
+        BankCard bankCard = new BankCard();
+        bankCard.setUserId(Long.valueOf(userid));
+        List<BankCard> list = bankCardService.selectBankCardList(bankCard);
+        return success(MessageUtils.message("no.load.success"), list);
+    }
+    //添加银行卡
+    @Anonymous
+    @Auth
+    @PostMapping("/addbankcard")
+    public AjaxResult addbankcard(@RequestHeader String token, @RequestBody BankCard bankCard)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        bankCard.setUserId(Long.valueOf(jwtUtil.getusid(token)));
+        return toAjax(bankCardService.insertBankCard(bankCard));
+    }
+    /**
+     * 查询BankCard列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:card:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BankCard bankCard)
+    {
+        startPage();
+        List<BankCard> list = bankCardService.selectBankCardList(bankCard);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出BankCard列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:card:export')")
+    @Log(title = "BankCard", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BankCard bankCard)
+    {
+        List<BankCard> list = bankCardService.selectBankCardList(bankCard);
+        ExcelUtil<BankCard> util = new ExcelUtil<BankCard>(BankCard.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.bankcard"));
+    }
+
+    /**
+     * 获取BankCard详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:card:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bankCardService.selectBankCardById(id));
+    }
+
+    /**
+     * 新增BankCard
+     */
+    @PreAuthorize("@ss.hasPermi('system:card:add')")
+    @Log(title = "BankCard", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BankCard bankCard)
+    {
+        return toAjax(bankCardService.insertBankCard(bankCard));
+    }
+
+    /**
+     * 修改BankCard
+     */
+    @PreAuthorize("@ss.hasPermi('system:card:edit')")
+    @Log(title = "BankCard", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BankCard bankCard)
+    {
+        return toAjax(bankCardService.updateBankCard(bankCard));
+    }
+
+    /**
+     * 删除BankCard
+     */
+    @PreAuthorize("@ss.hasPermi('system:card:remove')")
+    @Log(title = "BankCard", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bankCardService.deleteBankCardByIds(ids));
+    }
+}

+ 27 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/DisbursementController.java

@@ -0,0 +1,27 @@
+package com.ruoyi.app.pay;
+
+import com.ruoyi.app.utils.zaloPay.ZalopayDisbursement;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.domain.AjaxResult;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+/**
+ * 支出(取现)
+ * @Description: 支出(取现)
+ * @Author: Liyihao
+ * @Date: 2022/1/27 15:05
+ * @Version: V1.0
+ */
+@RestController
+@RequestMapping("/disbursement")
+public class DisbursementController {
+    @Anonymous
+    @RequestMapping("/verifyAccount")
+    public AjaxResult verifyAccount(String phone, long amount) throws Exception {
+        String result = ZalopayDisbursement.verifyAccount(phone,amount);
+        return AjaxResult.success("成功",result);
+    }
+
+}

+ 105 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/IpnLogController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.app.pay;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.IpnLog;
+import com.ruoyi.system.service.IIpnLogService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * IpnLogController
+ * 
+ * @author ruoyi
+ * @date 2023-11-22
+ */
+@RestController
+@RequestMapping("/system/ipnlog")
+public class IpnLogController extends BaseController
+{
+    @Autowired
+    private IIpnLogService ipnLogService;
+
+    /**
+     * 查询IpnLog列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:ipnlog:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(IpnLog ipnLog)
+    {
+        startPage();
+        List<IpnLog> list = ipnLogService.selectIpnLogList(ipnLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出IpnLog列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:ipnlog:export')")
+    @Log(title = "IpnLog", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, IpnLog ipnLog)
+    {
+        List<IpnLog> list = ipnLogService.selectIpnLogList(ipnLog);
+        ExcelUtil<IpnLog> util = new ExcelUtil<IpnLog>(IpnLog.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.ipnlog"));
+    }
+
+    /**
+     * 获取IpnLog详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:ipnlog:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(ipnLogService.selectIpnLogById(id));
+    }
+
+    /**
+     * 新增IpnLog
+     */
+    @PreAuthorize("@ss.hasPermi('system:ipnlog:add')")
+    @Log(title = "IpnLog", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody IpnLog ipnLog)
+    {
+        return toAjax(ipnLogService.insertIpnLog(ipnLog));
+    }
+
+    /**
+     * 修改IpnLog
+     */
+    @PreAuthorize("@ss.hasPermi('system:ipnlog:edit')")
+    @Log(title = "IpnLog", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody IpnLog ipnLog)
+    {
+        return toAjax(ipnLogService.updateIpnLog(ipnLog));
+    }
+
+    /**
+     * 删除IpnLog
+     */
+    @PreAuthorize("@ss.hasPermi('system:ipnlog:remove')")
+    @Log(title = "IpnLog", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(ipnLogService.deleteIpnLogByIds(ids));
+    }
+}

+ 446 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/PayController.java

@@ -0,0 +1,446 @@
+package com.ruoyi.app.pay;
+
+
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.order.dto.OrderPushBodyDto;
+import com.ruoyi.app.utils.*;
+import com.ruoyi.app.utils.event.PushEventService;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.domain.vo.PayResponse;
+import com.ruoyi.system.domain.vo.PayVN;
+import com.ruoyi.system.mapper.RiderPositionMapper;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import lombok.SneakyThrows;
+import org.apache.poi.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.text.DecimalFormat;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import static java.lang.Thread.sleep;
+
+@RestController
+@RequestMapping("/pay")
+public class PayController extends BaseController {
+    private static final Logger log = LoggerFactory.getLogger(PayController.class);
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IUserMarginService userMarginService;
+    @Autowired
+    private IUserBillingService userBillingService;
+    @Autowired
+    private IIpnLogService ipnLogService;
+    @Autowired
+    private RiderPositionMapper riderPositionMapper;
+    @Autowired
+    private PushEventService pushEventService;
+
+
+    //VNPay
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/VNPay", method = {RequestMethod.GET, RequestMethod.POST})
+    public AjaxResult VNPay(@RequestParam(defaultValue = "") String language, @RequestParam String orderid, @RequestParam String amount, HttpServletRequest request) {
+
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        Md5Pay md5Pay = new Md5Pay();
+        String obj = md5Pay.VNPay(language, orderid, amount, ip);
+        QueryWrapper<PosOrder> wrapper = new QueryWrapper<>();
+        wrapper.eq("dd_id", orderid);
+        PosOrder posOrder = posOrderService.getOne(wrapper);
+        if (posOrder == null) {
+            return error(MessageUtils.message("no.order.id.error"));
+        } else {
+            PosOrder pos = new PosOrder();
+            pos.setId(posOrder.getId());
+            pos.setPayUrl(obj);
+            pos.setPayType("2");
+            posOrderService.saveOrUpdate(pos);
+            return success(MessageUtils.message("no.order.create.success"), obj);
+        }
+    }
+
+
+    //查询支付订单
+    @SneakyThrows
+    @Anonymous
+    @RequestMapping(value = "/getVNPayorder", method = {RequestMethod.POST})
+    public AjaxResult getVNPayorder(@RequestBody PayResponse payResponse, HttpServletRequest request) {
+
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        Md5Pay md5Pay = new Md5Pay();
+        String obj = md5Pay.getPay(payResponse, ip);
+        JSONObject json = JSONUtil.toBean(obj, JSONObject.class);
+        return success(json);
+    }
+
+    //(售后退款)退款请求
+    @SneakyThrows
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/VNtuikuan", method = {RequestMethod.GET, RequestMethod.POST})
+    public AjaxResult VNtuikuan(@RequestHeader String token, @RequestBody PayVN payVN, HttpServletRequest request) {
+
+        JwtUtil jwtUtil = new JwtUtil();
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        String id = jwtUtil.getusid(token);
+        InfoUser user = infoUserService.getById(id);
+        System.out.println("退款用户信息:" + user.getPhone());
+//            DateUtil dateUtil = new DateUtil();
+        Md5Pay md5Pay = new Md5Pay();
+        payVN.setIpaddr(ip);
+        payVN.setUser(user.getPhone());
+        String obj = md5Pay.doPost(payVN);
+        JSONObject json = JSONUtil.toBean(obj, JSONObject.class);
+        QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+        wrapper.eq("dd_id", payVN.getOrder_id());
+        wrapper.eq("user_id", id);
+        wrapper.eq("type", "3");
+        wrapper.eq("state", "0");
+        UserBilling billing = userBillingService.getOne(wrapper);
+        System.out.println("退款结果代码:" + json.get("vnp_ResponseCode"));
+        if (json.get("vnp_ResponseCode").equals("00")) {
+            if (payVN.getTrantype().equals("02")) {
+                billing.setState("2");
+                userBillingService.saveOrUpdate(billing);
+            } else {
+                UserBilling usbi = new UserBilling();
+                usbi.setUserId(Long.valueOf(id));
+                usbi.setType("3");
+                usbi.setDdId(payVN.getOrder_id());
+                usbi.setAmount(Double.valueOf(payVN.getAmount()));
+                usbi.setMdId(billing.getMdId());
+                usbi.setIllustrate(payVN.getIllustrate());
+                usbi.setState("1");
+                userBillingService.saveOrUpdate(usbi);
+            }
+            return success(json);
+        } else {
+            return success(json);
+        }
+    }
+
+
+
+    /**
+     * 设置订单取消状态
+     *
+     * @param orderId
+     */
+    public void setCancelPayOrder(Long orderId) {
+        PosOrder order = new PosOrder();
+        order.setId(orderId);
+        order.setState(10L);
+        posOrderService.saveOrUpdate(order);
+    }
+
+
+    //接收IPN支付回调
+    @Anonymous
+    @RequestMapping(value = "/payipn", method = {RequestMethod.GET, RequestMethod.POST})
+    public JSONObject payipn(HttpServletRequest request) {
+        JSONObject org = new JSONObject();
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        Map map = new HashMap();
+        Enumeration paramNames = request.getParameterNames();
+        while (paramNames.hasMoreElements()) {
+            String paramName = (String) paramNames.nextElement();
+            String[] paramValues = request.getParameterValues(paramName);
+            if (paramValues.length == 1) {
+                String paramValue = paramValues[0];
+                if (paramValue.length() != 0) {
+                    map.put(paramName, paramValue);
+                }
+            }
+        }
+        System.out.println("IP : " + ip);
+        IpnLog log = new IpnLog();
+        log.setIp(ip);
+        log.setIpnLog(map.toString());
+        ipnLogService.insertIpnLog(log);
+        if (ip.equals("1.34.167.110") || ip.equals("113.160.92.202") || ip.equals("113.52.45.78") || ip.equals("116.97.245.130") || ip.equals("42,118,107.252") || ip.equals("113.20.97.250") || ip.equals("203.171.19.146") || ip.equals("127.0.0.1")) {
+            String vnp_SecureHash = map.get("vnp_SecureHash").toString();
+            if (map.containsKey("vnp_SecureHashType")) {
+                map.remove("vnp_SecureHashType");
+            }
+            if (map.containsKey("vnp_SecureHash")) {
+                map.remove("vnp_SecureHash");
+            }
+            String signValue = VNPay.hashAllFields(map);
+            PayPush push = new PayPush();
+            String orderid = map.get("vnp_TxnRef").toString().substring(0, 2);
+            System.out.println("回调信息" + map);
+            System.out.println("订单号:" + map.get("vnp_TxnRef").toString());
+            System.out.println("远程取回vnp_SecureHash:" + vnp_SecureHash);
+            System.out.println("本地计算vnp_SecureHash:" + signValue);
+            if (signValue.equals(vnp_SecureHash)) {
+                if ("00".equals(request.getParameter("vnp_ResponseCode"))) {
+                    if (orderid.equals("CZ")) {
+                        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
+                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
+                        UserBilling billing = userBillingService.getOne(queryWrapper);
+                        if (billing == null) {
+                            org.put("RspCode", "01");
+                            org.put("Message", "Order not Found");
+                        } else {
+
+                            InfoUser user = infoUserService.getById(billing.getUserId());
+                            String amount = map.get("vnp_Amount").toString();
+                            Double oramout = billing.getAmount() * 100;
+                            DecimalFormat df = new DecimalFormat("0.##");
+                            String s = df.format(oramout);
+                            System.out.println("金额对比:" + amount + "/" + s);
+                            if (amount.equals(s)) {
+                                if (billing.getState().equals("3")) {
+                                    UserBilling usbi = new UserBilling();
+                                    usbi.setId(billing.getId());
+                                    usbi.setState(String.valueOf(0));
+                                    userBillingService.saveOrUpdate(usbi);
+                                    Map<String, Object> orderMap=OrderPushBodyDto.getMap(billing.getDdId(),billing.getState(),-1,2);
+                                    String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
+                                    if (user.getUserType().equals("1")) {
+//                                        push.shpush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"), String.valueOf(map));
+
+                                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"), json);
+                                    } else {
+                                        push.qspush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"),json);
+                                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"), json);
+                                    }
+                                } else {
+                                    org.put("RspCode", "02");
+                                    org.put("Message", "Order already confirmed");
+                                }
+                            } else {
+                                org.put("RspCode", "04");
+
+                            }
+                        }
+                    } else
+                    {
+                        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
+                        PosOrder posOrder = posOrderService.getOne(queryWrapper);
+                        if (posOrder == null) {
+                            System.out.println("订单不存在============");
+                            org.put("RspCode", "01");
+                            org.put("Message", "Order not Found");
+                        } else {
+                            InfoUser user = infoUserService.getById(posOrder.getUserId());
+                            InfoUser shanghu = infoUserService.getById(posOrder.getShId());
+                            String amount = map.get("vnp_Amount").toString();
+                            int oramout = posOrder.getAmount() * 100;
+//                            DecimalFormat df = new DecimalFormat("0.##");
+                            String s = String.valueOf(oramout);
+                            System.out.println("金额对比:" + amount + "/" + s);
+                            if (amount.equals(s)) {
+                                System.out.println("订单状态:" + posOrder.getState());
+                                if (posOrder.getState() == 0) {
+                                    PosOrder order = new PosOrder();
+                                    order.setId(posOrder.getId());
+                                    order.setState(1L);
+                                    posOrderService.saveOrUpdate(order);
+                                    QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+                                    wrapper.eq("dd_id", posOrder.getDdId());
+                                    wrapper.eq("type", "3");
+                                    wrapper.eq("state", "3");
+                                    UserBilling billing = userBillingService.getOne(wrapper);
+                                    if (billing != null) {
+                                        billing.setState("0");
+                                        billing.setAmount(Double.valueOf(amount));
+                                        billing.setIllustrate("VNPayConsumer payment");
+                                        billing.setPaymentMethod("VNPay");
+                                        userBillingService.saveOrUpdate(billing);
+                                    }
+                                    Map<String, Object> orderMap=OrderPushBodyDto.getMap(String.valueOf(posOrder.getDdId()),"1",0,1);
+                                    String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
+                                    System.out.println("======================================推送支付结果");
+                                    push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.success"), json);
+                                    pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.success"), json);
+                                    push.shpush(shanghu.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), json);
+                                    pushEventService.PublisherEvent(shanghu.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), json);
+                                    sendAcceptRiderPush(posOrder, push, riderPositionMapper,OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),1));
+                                    org.put("RspCode", "00");
+                                    org.put("Message", "Confirm Success");
+                                } else {
+                                    org.put("RspCode", "02");
+                                    org.put("Message", "Order already confirmed");
+                                }
+                            } else {
+                                org.put("RspCode", "04");
+                                org.put("Message", "Invalid amount");
+                            }
+                        }
+                    }
+                } else {
+                    if (orderid.equals("CZ")) {
+                        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
+                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
+                        UserBilling billing = userBillingService.getOne(queryWrapper);
+                        InfoUser user = infoUserService.getById(billing.getUserId());
+                        Map<String, Object> orderMap=OrderPushBodyDto.getMap(billing.getDdId(),billing.getState(),-1,2);
+                        String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
+                        push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"), String.valueOf(map));
+                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"), json);
+                    } else {
+                        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
+                        PosOrder posOrder = posOrderService.getOne(queryWrapper);
+                        Map<String, Object> orderMap=OrderPushBodyDto.getMap(String.valueOf(posOrder.getDdId()),"0",-1,1);
+                        String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
+                        InfoUser user = infoUserService.getById(posOrder.getUserId());
+                        push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"),json);
+                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"), json);
+                    }
+                    org.put("RspCode", "00");
+                    org.put("Message", "Confirm Success");
+                }
+
+            } else {
+                // Sai checksum
+                System.out.println("h값不一至===================");
+                org.put("RspCode", "97");
+                org.put("Message", "Invalid Checksum");
+            }
+            return org;
+        } else {
+            org.put("RspCode", "99");
+            org.put("Message", "Illegal IP access");
+            return org;
+        }
+
+    }
+
+    /**
+     * 推送可接单骑手
+     *
+     * @param order
+     * @param push
+     */
+    @Async(value = "threadPoolTaskExecutor")
+    public void sendAcceptRiderPush(PosOrder order, PayPush push, RiderPositionMapper riderPositionMapper,String body) {
+        // type=0外送,CollectPayment=1 到付
+        if(order.getState()!=0){
+            return;
+        }
+        List<RiderPosition> riders = riderPositionMapper.getAcceptRiderList(order.getLongitude(), order.getLatitude(), 20);
+
+        List<RiderPosition> validRiders = riders.stream()
+                .filter(x -> x.getCid() != null && !x.getCid().isEmpty())
+                .collect(Collectors.toList());
+        int taskCount = validRiders.size();
+        CountDownLatch latch = new CountDownLatch(taskCount);
+        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
+        for (int i = 0; i < taskCount; i++) {
+            RiderPosition rider = validRiders.get(i);
+            final int index = i;
+
+            scheduler.schedule(() -> {
+                try {
+                    System.out.println("========== 可接单骑手推送 ==========cid:" + rider.getCid() + "riderId:" + rider.getRiderId() + ",mapJson:" + body);
+                    push.qspush(rider.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
+                    );
+                    pushEventService.PublisherEvent(rider.getRiderId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
+                    );
+                } catch (Exception e) {
+                    log.error("推送骑手异常", e);
+                } finally {
+                    // 无论成功与否,都减少计数
+                    latch.countDown();
+                }
+            }, i * 2L, TimeUnit.SECONDS);
+        }
+
+        // 另启一个线程等待所有任务完成,然后关闭调度器
+        scheduler.submit(() -> {
+            try {
+                // 等待所有任务完成(超时时间设置为总间隔时间+额外缓冲)
+                long timeout = (taskCount * 2L) + 10; // 额外10秒缓冲
+                if (latch.await(timeout, TimeUnit.SECONDS)) {
+                    log.info("所有骑手推送完成");
+                } else {
+                    log.warn("骑手推送超时,仍有{}个任务未完成", latch.getCount());
+                }
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            } finally {
+                // 关闭调度器
+                scheduler.shutdown();
+            }
+        });
+
+
+//        if (order.getType() == 0) {
+//            List<RiderPosition> riders = riderPositionMapper.getAcceptRiderList(order.getLongitude(), order.getLatitude(), 20);
+//            riders.stream().filter(x -> x.getCid() != null && !x.getCid().isEmpty()).forEach(x -> {
+//
+//                System.out.println("========== 可接单骑手推送 ==========cid:" + x.getCid() + "riderId:" + x.getRiderId() + ",mapJson:" + body);
+//                push.qspush(x.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
+//                );
+//                pushEventService.PublisherEvent(x.getRiderId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
+//                );
+//
+//                try {
+//                    Thread.sleep(2000);
+//                } catch (InterruptedException e) {
+//                    log.error("线程睡眠异常", e);
+//                }
+//
+//            });
+//        }
+    }
+
+    @Anonymous
+    @RequestMapping(value = "/payJson", method = {RequestMethod.GET, RequestMethod.POST})
+    public AjaxResult payJson(HttpServletRequest request) {
+        Map map = new HashMap();
+        Enumeration paramNames = request.getParameterNames();
+        while (paramNames.hasMoreElements()) {
+            String paramName = (String) paramNames.nextElement();
+            String[] paramValues = request.getParameterValues(paramName);
+            if (paramValues.length == 1) {
+                String paramValue = paramValues[0];
+                if (paramValue.length() != 0) {
+                    map.put(paramName, paramValue);
+                }
+            }
+        }
+        return success("success", "");
+    }
+
+
+}

+ 401 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java

@@ -0,0 +1,401 @@
+package com.ruoyi.app.pay;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.order.ZaloPayCommonService;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.IpUtils;
+import com.ruoyi.app.utils.Md5Pay;
+import com.ruoyi.app.utils.zaloPay.ZaloPay;
+import com.ruoyi.app.utils.zaloPay.ZaloPayConfig;
+import com.ruoyi.app.utils.zaloPay.ZaloPayCreateOrderResponse;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.UserBilling;
+import com.ruoyi.system.domain.vo.BillDTO;
+import com.ruoyi.system.mapper.UserBillingMapper;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.service.IPosOrderService;
+import com.ruoyi.system.service.IUserBillingService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * BillingController
+ *
+ * @author ruoyi
+ * @date 2023-09-06
+ */
+@RestController
+@RequestMapping("/Billing/billing")
+public class UserBillingController extends BaseController
+{
+    @Autowired
+    private IUserBillingService userBillingService;
+    @Autowired
+    private UserBillingMapper userBillingMapper;
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private ZaloPayCommonService zaloPayCommonService;
+    @Autowired
+    private ZaloPayConfig zaloPayConfig;
+    @Autowired
+    private ZaloPay zaloPay;
+
+    /**
+     * 商家日账单数据
+     * @param token
+     * @param page
+     * @param size
+     * @param riqi
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getzddaylist")
+    public AjaxResult getzddaylist(@RequestHeader String token,
+                                    @RequestParam Long page,
+                                    @RequestParam Long size,
+                                    @RequestParam String riqi)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        List<UserBilling> list = userBillingMapper.getdaylist(id,riqi,(page-1)*size,size);
+        setYhInfo(list);
+        BillDTO sum = userBillingMapper.getdaysum(id,riqi);
+        JSONObject org = new JSONObject();
+        org.put("shul",sum.getSul());
+        org.put("sum",sum.getShouru());
+        org.put("list",list);
+        return success(MessageUtils.message("no.success"), org);
+    }
+
+    /**
+     * 商家周账单数据
+     * @param token
+     * @param page
+     * @param size
+     * @param riqi
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getzdmeeklist")
+    public AjaxResult getzdmeeklist(@RequestHeader String token,
+                                   @RequestParam Long page,
+                                   @RequestParam Long size,
+                                   @RequestParam String riqi)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        List<UserBilling> list = userBillingMapper.getmeeklist(id,riqi,(page-1)*size,size);
+        setYhInfo(list);
+        BillDTO sum = userBillingMapper.getmeeksum(id,riqi);
+        JSONObject org = new JSONObject();
+        org.put("shul",sum.getSul());
+        org.put("sum",sum.getShouru());
+        org.put("list",list);
+        return success(MessageUtils.message("no.success"), org);
+    }
+
+    private void setYhInfo(List<UserBilling> list) {
+        if(!list.isEmpty()){
+            List<String> orderIds=list.stream().map(UserBilling::getDdId).collect(Collectors.toList());
+            LambdaQueryWrapper<PosOrder> query = new LambdaQueryWrapper<>();
+            query.in(PosOrder::getDdId,orderIds);
+            List<PosOrder> orders = posOrderService.list(query);
+            list.forEach(billing -> {
+                orders.stream().filter(o -> o.getDdId().toString().equals(billing.getDdId())).findFirst().ifPresent(o -> {
+                    billing.setActivity(o.getActivity());
+                    billing.setMdActivity(o.getMdActivity());
+                    billing.setMdActivity(o.getMdActivity());
+                    billing.setYhId(o.getYhId());
+                    billing.setYhName(o.getYhName());
+                    billing.setDiscountAmount(o.getDiscountAmount());
+                    billing.setMdYhId(o.getMdYhId());
+                    billing.setMdYhName(o.getMdYhName());
+                    billing.setMdDiscountAmount(o.getMdDiscountAmount());
+                    billing.setSalesName(o.getSalesName());
+                    billing.setMdSalesName(o.getMdSalesName());
+                    billing.setSalesReduction(o.getSalesReduction());
+                    billing.setMdSalesReduction(o.getMdSalesReduction());
+                    billing.setPoints(o.getPoints());
+                    billing.setPointsReduction(o.getPointsReduction());
+                });
+            });
+        }
+    }
+
+    /**
+     * 商家月账单数据
+     * @param token
+     * @param page
+     * @param size
+     * @param riqi
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getzdmatlist")
+    public AjaxResult getzdmatlist(@RequestHeader String token,
+                                @RequestParam Long page,
+                                @RequestParam Long size,
+                                @RequestParam String riqi)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        List<UserBilling> list = userBillingMapper.getmatlist(id,riqi,(page-1)*size,size);
+        setYhInfo(list);
+        BillDTO sum = userBillingMapper.getmatsum(id,riqi);
+        JSONObject org = new JSONObject();
+        org.put("shul",sum.getSul());
+        org.put("sum",sum.getShouru());
+        org.put("list",list);
+        return success(MessageUtils.message("no.success"), org);
+    }
+
+    //充值
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/userRecharge", method = {RequestMethod.GET,RequestMethod.POST})
+    public AjaxResult userRecharge(@RequestHeader String token, @RequestParam String language, @RequestParam Long amount, HttpServletRequest request)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        String id = jwtUtil.getusid(token);
+        Long timeLong = System.currentTimeMillis();
+        Md5Pay md5Pay = new Md5Pay();
+        String orderid = "CZ"+timeLong;
+        System.out.println("orderid:"+orderid);
+        String obj =  md5Pay.VNPay(language,orderid,String.valueOf(amount),ip);
+        UserBilling billing = new UserBilling();
+        billing.setUserId(Long.valueOf(id));
+        billing.setType(String.valueOf(1));
+        billing.setDdId(orderid);
+        billing.setAmount(Double.valueOf(amount));
+        billing.setState(String.valueOf(3));
+        billing.setIllustrate("用户充值");
+        billing.setPaymentMethod("app线上充值");
+        billing.setUrl(obj);
+        Boolean reg = userBillingService.saveOrUpdate(billing);
+        if(reg){
+            return success(MessageUtils.message("no.order.create.success"), obj);
+        }else {
+            return error();
+        }
+    }
+
+
+    /**
+     *  充值使用ZaloPay
+     * @param token
+     * @param language
+     * @param amount
+     * @param request
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/userRechargeZaloPay", method = {RequestMethod.GET,RequestMethod.POST})
+    public AjaxResult userRechargeZaloPay(@RequestHeader String token, @RequestParam String language, @RequestParam Long amount,@RequestParam String payType, HttpServletRequest request) throws Exception {
+        JwtUtil jwtUtil = new JwtUtil();
+        String userId = jwtUtil.getusid(token);
+        Long timeLong = System.currentTimeMillis();
+        String orderid = "CZ"+timeLong;
+        System.out.println("orderid:"+orderid);
+        ZaloPayCreateOrderResponse obj =  zaloPay.createOrder(userId,orderid,amount,"user recharch by zalopay",zaloPayConfig.getZaloPayConfig(payType));
+        zaloPayCommonService.setZaloPayOrder(orderid, JSON.toJSONString(obj),null,null,null,payType);
+        UserBilling billing = new UserBilling();
+        billing.setUserId(Long.valueOf(userId));
+        billing.setType(String.valueOf(1));
+        billing.setDdId(orderid);
+        billing.setAmount(Double.valueOf(amount));
+        billing.setState(String.valueOf(3));
+        billing.setIllustrate("用户充值");
+        billing.setPaymentMethod("zalopay线上充值");
+        billing.setUrl(JSONObject.toJSONString(obj));
+        Boolean reg = userBillingService.saveOrUpdate(billing);
+        if(reg){
+            return success(MessageUtils.message("no.order.create.success"), obj);
+        }else {
+            return error();
+        }
+    }
+
+
+    //查询用户账户及余额
+    @Anonymous
+    @Auth
+    @GetMapping("/getUsbalance")
+    public AjaxResult getUsbalance(@RequestHeader String token,
+                                   @RequestParam Integer page,
+                                   @RequestParam Integer size,
+                                   @RequestParam boolean sort,
+                                   @RequestParam(defaultValue = "") String type)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        DateUtil dateUtil = new DateUtil();
+        String id = jwtUtil.getusid(token);
+        if (!"".equals(type)){
+            JSONObject org = new JSONObject();
+            IPage<UserBilling> palist = new Page<>(page,size);
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            int sumlist = userBillingMapper.gettypesum(Long.valueOf(id), Long.valueOf(type));
+            wrapper.eq("user_id",id);
+            wrapper.eq("type",type);
+            wrapper.orderBy(true, sort, "cretim");
+            IPage<UserBilling> mmlist =  userBillingService.page(palist,wrapper);
+            List<UserBilling> list = mmlist.getRecords();
+            JSONArray arr = new JSONArray();
+            for(int i=0;i<list.size();i++){
+                JSONObject ject = new JSONObject();
+                ject.put("id",list.get(i).getId());
+                ject.put("user",infoUserService.getById(list.get(i).getUserId()));
+                ject.put("type",list.get(i).getType());
+                PosOrder order = posOrderService.getById(list.get(i).getDdId());
+                ject.put("ddId",order==null?list.get(i).getDdId():order.getDdId());
+                ject.put("amount",list.get(i).getAmount());
+                ject.put("divvy",list.get(i).getDivvy());
+                ject.put("state",list.get(i).getState());
+                ject.put("mdId",list.get(i).getMdId());
+                ject.put("illustrate",list.get(i).getIllustrate());
+                ject.put("paymentMethod",list.get(i).getPaymentMethod());
+                ject.put("accountNumber",list.get(i).getAccountNumber());
+                ject.put("url",list.get(i).getUrl());
+                ject.put("cretim",dateUtil.setDate(list.get(i).getCretim()));
+                arr.add(ject);
+            }
+            org.put("sum",sumlist);
+            org.put("list",arr);
+            return success(MessageUtils.message("no.success"), org);
+        }else {
+            JSONObject org = new JSONObject();
+            IPage<UserBilling> palist = new Page<>(page,size);
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            int zlist = userBillingMapper.gettypesum(Long.valueOf(id), 1L);
+            int txlist = userBillingMapper.gettypesum(Long.valueOf(id), 2L);
+            int xfei = userBillingMapper.gettypesum(Long.valueOf(id), 3L);
+            wrapper.eq("user_id",id);
+            wrapper.orderBy(true, sort, "cretim");
+            IPage<UserBilling> mmlist =  userBillingService.page(palist,wrapper);
+            List<UserBilling> list = mmlist.getRecords();
+            JSONArray arr = new JSONArray();
+            for(int i=0;i<list.size();i++){
+                JSONObject ject = new JSONObject();
+                ject.put("id",list.get(i).getId());
+                ject.put("user",infoUserService.getById(list.get(i).getUserId()));
+                ject.put("type",list.get(i).getType());
+                PosOrder order = posOrderService.getById(list.get(i).getDdId());
+                ject.put("ddId",order==null?list.get(i).getDdId():order.getDdId());
+                ject.put("amount",list.get(i).getAmount());
+                ject.put("divvy",list.get(i).getDivvy());
+                ject.put("state",list.get(i).getState());
+                ject.put("mdId",list.get(i).getMdId());
+                ject.put("illustrate",list.get(i).getIllustrate());
+                ject.put("paymentMethod",list.get(i).getPaymentMethod());
+                ject.put("accountNumber",list.get(i).getAccountNumber());
+                ject.put("cretim",dateUtil.setDate(list.get(i).getCretim()));
+                ject.put("url",list.get(i).getUrl());
+                arr.add(ject);
+            }
+            int sum = zlist-txlist-xfei;
+            org.put("sum",sum);
+            org.put("list",arr);
+            return success(MessageUtils.message("no.success"), org);
+        }
+    }
+    /**
+     * 查询Billing列表
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(UserBilling userBilling)
+    {
+        startPage();
+        List<UserBilling> list = userBillingService.selectUserBillingList(userBilling);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出Billing列表
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:export')")
+    @Log(title = "Billing", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, UserBilling userBilling)
+    {
+        List<UserBilling> list = userBillingService.selectUserBillingList(userBilling);
+        ExcelUtil<UserBilling> util = new ExcelUtil<UserBilling>(UserBilling.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.billing"));
+    }
+
+    /**
+     * 获取Billing详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(userBillingService.selectUserBillingById(id));
+    }
+
+    /**
+     * 新增Billing
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:add')")
+    @Log(title = "Billing", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody UserBilling userBilling)
+    {
+        return toAjax(userBillingService.insertUserBilling(userBilling));
+    }
+
+    /**
+     * 修改Billing
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:edit')")
+    @Log(title = "Billing", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody UserBilling userBilling)
+    {
+        return toAjax(userBillingService.updateUserBilling(userBilling));
+    }
+
+    /**
+     * 删除Billing
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:remove')")
+    @Log(title = "Billing", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(userBillingService.deleteUserBillingByIds(ids));
+    }
+}

+ 401 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java~

@@ -0,0 +1,401 @@
+package com.ruoyi.app.pay;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.app.order.ZaloPayCommonService;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.IpUtils;
+import com.ruoyi.app.utils.Md5Pay;
+import com.ruoyi.app.utils.zaloPay.ZaloPay;
+import com.ruoyi.app.utils.zaloPay.ZaloPayConfig;
+import com.ruoyi.app.utils.zaloPay.ZaloPayCreateOrderResponse;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.UserBilling;
+import com.ruoyi.system.domain.vo.BillDTO;
+import com.ruoyi.system.mapper.UserBillingMapper;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.service.IPosOrderService;
+import com.ruoyi.system.service.IUserBillingService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * BillingController
+ *
+ * @author ruoyi
+ * @date 2023-09-06
+ */
+@RestController
+@RequestMapping("/Billing/billing")
+public class UserBillingController extends BaseController
+{
+    @Autowired
+    private IUserBillingService userBillingService;
+    @Autowired
+    private UserBillingMapper userBillingMapper;
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private ZaloPayCommonService zaloPayCommonService;
+    @Autowired
+    private ZaloPayConfig zaloPayConfig;
+    @Autowired
+    private ZaloPay zaloPay;
+
+    /**
+     * 商家日账单数据
+     * @param token
+     * @param page
+     * @param size
+     * @param riqi
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getzddaylist")
+    public AjaxResult getzddaylist(@RequestHeader String token,
+                                    @RequestParam Long page,
+                                    @RequestParam Long size,
+                                    @RequestParam String riqi)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        List<UserBilling> list = userBillingMapper.getdaylist(id,riqi,(page-1)*size,size);
+        setYhInfo(list);
+        BillDTO sum = userBillingMapper.getdaysum(id,riqi);
+        JSONObject org = new JSONObject();
+        org.put("shul",sum.getSul());
+        org.put("sum",sum.getShouru());
+        org.put("list",list);
+        return success(MessageUtils.message("no.success"), org);
+    }
+
+    /**
+     * 商家周账单数据
+     * @param token
+     * @param page
+     * @param size
+     * @param riqi
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getzdmeeklist")
+    public AjaxResult getzdmeeklist(@RequestHeader String token,
+                                   @RequestParam Long page,
+                                   @RequestParam Long size,
+                                   @RequestParam String riqi)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        List<UserBilling> list = userBillingMapper.getmeeklist(id,riqi,(page-1)*size,size);
+        setYhInfo(list);
+        BillDTO sum = userBillingMapper.getmeeksum(id,riqi);
+        JSONObject org = new JSONObject();
+        org.put("shul",sum.getSul());
+        org.put("sum",sum.getShouru());
+        org.put("list",list);
+        return success(MessageUtils.message("no.success"), org);
+    }
+
+    private void setYhInfo(List<UserBilling> list) {
+        if(!list.isEmpty()){
+            List<String> orderIds=list.stream().map(UserBilling::getDdId).collect(Collectors.toList());
+            LambdaQueryWrapper<PosOrder> query = new LambdaQueryWrapper<>();
+            query.in(PosOrder::getDdId,orderIds);
+            List<PosOrder> orders = posOrderService.list(query);
+            list.forEach(billing -> {
+                orders.stream().filter(o -> o.getDdId().toString().equals(billing.getDdId())).findFirst().ifPresent(o -> {
+                    billing.setActivity(o.getActivity());
+                    billing.setMdActivity(o.getMdActivity());
+                    billing.setMdActivity(o.getMdActivity());
+                    billing.setYhId(o.getYhId());
+                    billing.setYhName(o.getYhName());
+                    billing.setDiscountAmount(o.getDiscountAmount());
+                    billing.setMdYhId(o.getMdYhId());
+                    billing.setMdYhName(o.getMdYhName());
+                    billing.setMdDiscountAmount(o.getMdDiscountAmount());
+                    billing.setSalesName(o.getSalesName());
+                    billing.setMdSalesName(o.getMdSalesName());
+                    billing.setSalesReduction(o.getSalesReduction());
+                    billing.setMdSalesReduction(o.getMdSalesReduction());
+                    billing.setPoints(o.getPoints());
+                    billing.setPointsReduction(o.getPointsReduction());
+                });
+            });
+        }
+    }
+
+    /**
+     * 商家月账单数据
+     * @param token
+     * @param page
+     * @param size
+     * @param riqi
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getzdmatlist")
+    public AjaxResult getzdmatlist(@RequestHeader String token,
+                                @RequestParam Long page,
+                                @RequestParam Long size,
+                                @RequestParam String riqi)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        List<UserBilling> list = userBillingMapper.getmatlist(id,riqi,(page-1)*size,size);
+        setYhInfo(list);
+        BillDTO sum = userBillingMapper.getmatsum(id,riqi);
+        JSONObject org = new JSONObject();
+        org.put("shul",sum.getSul());
+        org.put("sum",sum.getShouru());
+        org.put("list",list);
+        return success(MessageUtils.message("no.success"), org);
+    }
+
+    //充值
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/userRecharge", method = {RequestMethod.GET,RequestMethod.POST})
+    public AjaxResult userRecharge(@RequestHeader String token, @RequestParam String language, @RequestParam Long amount, HttpServletRequest request)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        String id = jwtUtil.getusid(token);
+        Long timeLong = System.currentTimeMillis();
+        Md5Pay md5Pay = new Md5Pay();
+        String orderid = "CZ"+timeLong;
+        System.out.println("orderid:"+orderid);
+        String obj =  md5Pay.VNPay(language,orderid,String.valueOf(amount),ip);
+        UserBilling billing = new UserBilling();
+        billing.setUserId(Long.valueOf(id));
+        billing.setType(String.valueOf(1));
+        billing.setDdId(orderid);
+        billing.setAmount(Double.valueOf(amount));
+        billing.setState(String.valueOf(3));
+        billing.setIllustrate("用户充值");
+        billing.setPaymentMethod("app线上充值");
+        billing.setUrl(obj);
+        Boolean reg = userBillingService.saveOrUpdate(billing);
+        if(reg){
+            return success(MessageUtils.message("no.order.create.success"), obj);
+        }else {
+            return error();
+        }
+    }
+
+
+    /**
+     *  充值使用ZaloPay
+     * @param token
+     * @param language
+     * @param amount
+     * @param request
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/userRechargeZaloPay", method = {RequestMethod.GET,RequestMethod.POST})
+    public AjaxResult userRechargeZaloPay(@RequestHeader String token, @RequestParam String language, @RequestParam Long amount,@RequestParam String payType, HttpServletRequest request) throws Exception {
+        JwtUtil jwtUtil = new JwtUtil();
+        String userId = jwtUtil.getusid(token);
+        Long timeLong = System.currentTimeMillis();
+        String orderid = "CZ"+timeLong;
+        System.out.println("orderid:"+orderid);
+        ZaloPayCreateOrderResponse obj =  ZaloPay.createOrder(userId,orderid,amount,"user recharch by zalopay",zaloPayConfig.getZaloPayConfig(payType));
+        zaloPayCommonService.setZaloPayOrder(orderid, JSON.toJSONString(obj),null,null,null,payType);
+        UserBilling billing = new UserBilling();
+        billing.setUserId(Long.valueOf(userId));
+        billing.setType(String.valueOf(1));
+        billing.setDdId(orderid);
+        billing.setAmount(Double.valueOf(amount));
+        billing.setState(String.valueOf(3));
+        billing.setIllustrate("用户充值");
+        billing.setPaymentMethod("zalopay线上充值");
+        billing.setUrl(JSONObject.toJSONString(obj));
+        Boolean reg = userBillingService.saveOrUpdate(billing);
+        if(reg){
+            return success(MessageUtils.message("no.order.create.success"), obj);
+        }else {
+            return error();
+        }
+    }
+
+
+    //查询用户账户及余额
+    @Anonymous
+    @Auth
+    @GetMapping("/getUsbalance")
+    public AjaxResult getUsbalance(@RequestHeader String token,
+                                   @RequestParam Integer page,
+                                   @RequestParam Integer size,
+                                   @RequestParam boolean sort,
+                                   @RequestParam(defaultValue = "") String type)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        DateUtil dateUtil = new DateUtil();
+        String id = jwtUtil.getusid(token);
+        if (!"".equals(type)){
+            JSONObject org = new JSONObject();
+            IPage<UserBilling> palist = new Page<>(page,size);
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            int sumlist = userBillingMapper.gettypesum(Long.valueOf(id), Long.valueOf(type));
+            wrapper.eq("user_id",id);
+            wrapper.eq("type",type);
+            wrapper.orderBy(true, sort, "cretim");
+            IPage<UserBilling> mmlist =  userBillingService.page(palist,wrapper);
+            List<UserBilling> list = mmlist.getRecords();
+            JSONArray arr = new JSONArray();
+            for(int i=0;i<list.size();i++){
+                JSONObject ject = new JSONObject();
+                ject.put("id",list.get(i).getId());
+                ject.put("user",infoUserService.getById(list.get(i).getUserId()));
+                ject.put("type",list.get(i).getType());
+                PosOrder order = posOrderService.getById(list.get(i).getDdId());
+                ject.put("ddId",order==null?list.get(i).getDdId():order.getDdId());
+                ject.put("amount",list.get(i).getAmount());
+                ject.put("divvy",list.get(i).getDivvy());
+                ject.put("state",list.get(i).getState());
+                ject.put("mdId",list.get(i).getMdId());
+                ject.put("illustrate",list.get(i).getIllustrate());
+                ject.put("paymentMethod",list.get(i).getPaymentMethod());
+                ject.put("accountNumber",list.get(i).getAccountNumber());
+                ject.put("url",list.get(i).getUrl());
+                ject.put("cretim",dateUtil.setDate(list.get(i).getCretim()));
+                arr.add(ject);
+            }
+            org.put("sum",sumlist);
+            org.put("list",arr);
+            return success(MessageUtils.message("no.success"), org);
+        }else {
+            JSONObject org = new JSONObject();
+            IPage<UserBilling> palist = new Page<>(page,size);
+            QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+            int zlist = userBillingMapper.gettypesum(Long.valueOf(id), 1L);
+            int txlist = userBillingMapper.gettypesum(Long.valueOf(id), 2L);
+            int xfei = userBillingMapper.gettypesum(Long.valueOf(id), 3L);
+            wrapper.eq("user_id",id);
+            wrapper.orderBy(true, sort, "cretim");
+            IPage<UserBilling> mmlist =  userBillingService.page(palist,wrapper);
+            List<UserBilling> list = mmlist.getRecords();
+            JSONArray arr = new JSONArray();
+            for(int i=0;i<list.size();i++){
+                JSONObject ject = new JSONObject();
+                ject.put("id",list.get(i).getId());
+                ject.put("user",infoUserService.getById(list.get(i).getUserId()));
+                ject.put("type",list.get(i).getType());
+                PosOrder order = posOrderService.getById(list.get(i).getDdId());
+                ject.put("ddId",order==null?list.get(i).getDdId():order.getDdId());
+                ject.put("amount",list.get(i).getAmount());
+                ject.put("divvy",list.get(i).getDivvy());
+                ject.put("state",list.get(i).getState());
+                ject.put("mdId",list.get(i).getMdId());
+                ject.put("illustrate",list.get(i).getIllustrate());
+                ject.put("paymentMethod",list.get(i).getPaymentMethod());
+                ject.put("accountNumber",list.get(i).getAccountNumber());
+                ject.put("cretim",dateUtil.setDate(list.get(i).getCretim()));
+                ject.put("url",list.get(i).getUrl());
+                arr.add(ject);
+            }
+            int sum = zlist-txlist-xfei;
+            org.put("sum",sum);
+            org.put("list",arr);
+            return success(MessageUtils.message("no.success"), org);
+        }
+    }
+    /**
+     * 查询Billing列表
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(UserBilling userBilling)
+    {
+        startPage();
+        List<UserBilling> list = userBillingService.selectUserBillingList(userBilling);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出Billing列表
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:export')")
+    @Log(title = "Billing", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, UserBilling userBilling)
+    {
+        List<UserBilling> list = userBillingService.selectUserBillingList(userBilling);
+        ExcelUtil<UserBilling> util = new ExcelUtil<UserBilling>(UserBilling.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.billing"));
+    }
+
+    /**
+     * 获取Billing详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(userBillingService.selectUserBillingById(id));
+    }
+
+    /**
+     * 新增Billing
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:add')")
+    @Log(title = "Billing", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody UserBilling userBilling)
+    {
+        return toAjax(userBillingService.insertUserBilling(userBilling));
+    }
+
+    /**
+     * 修改Billing
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:edit')")
+    @Log(title = "Billing", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody UserBilling userBilling)
+    {
+        return toAjax(userBillingService.updateUserBilling(userBilling));
+    }
+
+    /**
+     * 删除Billing
+     */
+    @PreAuthorize("@ss.hasPermi('Billing:billing:remove')")
+    @Log(title = "Billing", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(userBillingService.deleteUserBillingByIds(ids));
+    }
+}

+ 475 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/pay/ZaloPayController.java

@@ -0,0 +1,475 @@
+package com.ruoyi.app.pay;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.order.ZaloPayCommonService;
+import com.ruoyi.app.order.dto.OrderPushBodyDto;
+import com.ruoyi.app.utils.*;
+import com.ruoyi.app.utils.event.PushEventService;
+import com.ruoyi.app.utils.zaloPay.*;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.domain.vo.PayVN;
+import com.ruoyi.system.mapper.RiderPositionMapper;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import lombok.SneakyThrows;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.bind.DatatypeConverter;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * ZaloPay支付控制器
+ **/
+@RestController
+@RequestMapping("/zaloPay")
+public class ZaloPayController extends BaseController {
+    private static final Logger log = LoggerFactory.getLogger(ZaloPayController.class);
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IUserMarginService userMarginService;
+    @Autowired
+    private IUserBillingService userBillingService;
+    @Autowired
+    private IIpnLogService ipnLogService;
+    @Autowired
+    private RiderPositionMapper riderPositionMapper;
+    @Autowired
+    private PayController payController;
+    @Autowired
+    private IPoseOrderZalopayService zalopayService;
+    @Autowired
+    private PushEventService pushEventService;
+    private Mac HmacSHA256;
+
+    @Autowired
+    private ZaloPayCommonService zaloPayCommonService;
+    @Autowired
+    private ZaloPayConfig zaloPayConfig;
+    @Autowired
+    private ZaloPay zaloPay;
+
+    public ZaloPayController() throws Exception  {
+        HmacSHA256 = Mac.getInstance("HmacSHA256");
+
+    }
+
+    /**
+     *  创建ZaloPay订单
+     */
+
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/ZaloPay", method = {RequestMethod.GET, RequestMethod.POST})
+    public AjaxResult ZaloPay(@RequestParam(defaultValue = "") String language,
+                              @RequestParam String orderId,
+                              @RequestParam String amount,
+                              @RequestParam String payType,
+                              HttpServletRequest request) throws Exception {
+        System.out.println("ZaloPay创建支付开始 orderId: " + orderId+ ", amount: " + amount);
+        LambdaQueryWrapper<PosOrder> wrapper = new LambdaQueryWrapper<>();
+        orderId=orderId.trim();
+        wrapper.eq(PosOrder::getDdId, orderId);
+        PosOrder posOrder = posOrderService.getOne(wrapper);
+        if (posOrder == null) {
+            System.out.println("no.order.id.error---order为null");
+            return error(MessageUtils.message("no.order.id.error"));
+        }
+        PoseOrderZalopay zaloResopen = zalopayService.getOne(new LambdaQueryWrapper<PoseOrderZalopay>().eq(PoseOrderZalopay::getDdId, orderId));
+        if(zaloResopen!=null && zaloResopen.getCreateResponse()!=null && zaloResopen.getCreateResponseTime()!=null){
+            long currentTimeMillis = System.currentTimeMillis();
+            long createResponseTimeMillis = zaloResopen.getCreateResponseTime().getTime();
+            long diffMinutes = (currentTimeMillis - createResponseTimeMillis) / (1000 * 60);
+            //ordertoken有效时间15分钟
+            if(diffMinutes<=14){
+                //该处计算当前时间比较创建时间,如果大于10分钟则认为订单已支付
+                return success(MessageUtils.message("no.order.create.success"), JSON.parseObject(zaloResopen.getCreateResponse(),ZaloPayCreateOrderResponse.class));
+            }
+        }
+        ZaloPayCreateOrderResponse response;
+        ZaloPayProperties.ZaloPayConfig config = zaloPayConfig.getZaloPayConfig(payType);
+        try {
+            response = zaloPay.createOrder(String.valueOf(posOrder.getUserId()), orderId, Long.parseLong(amount), "City Express-#" + posOrder.getDdId(),config);
+
+        } catch (Exception e) {
+            System.out.println("no.order.id.error---抛出异常");
+            // 记录详细错误信息以便调试
+            log.error("ZaloPay创建失败 orderId: {}, error: {}", orderId, e.getMessage(), e);
+            System.out.println("ZaloPay创建失败 orderId: " + orderId + ", error: " + e.getMessage());
+            return error(MessageUtils.message("no.order.id.error"));
+        }
+        if(response.getReturnCode()==2){
+            return error(response.getReturnMessage());
+        }
+        zaloPayCommonService.setZaloPayOrder(orderId,JSON.toJSONString(response),null,null,null,payType);
+        System.out.println("ZaloPay创建支付成功");
+        PosOrder pos = new PosOrder();
+        pos.setId(posOrder.getId());
+        pos.setPayType(payType);
+        posOrderService.saveOrUpdate(pos);
+        return success(MessageUtils.message("no.order.create.success"), response);
+    }
+
+
+    //查询支付订单
+
+    @SneakyThrows
+    @Anonymous
+    @RequestMapping(value = "/getZaloPayorder", method = {RequestMethod.GET})
+    public AjaxResult getZaloPayorder(@RequestParam String ddId) {
+        PoseOrderZalopay zaloResopen = zalopayService.getOne(new QueryWrapper<PoseOrderZalopay>().eq("dd_id", ddId));
+        if(zaloResopen==null){
+            return error("未查到支付信息");
+        }
+        Date createResponseTime = zaloResopen.getCreateResponseTime();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
+        String formattedDate = sdf.format(createResponseTime);
+        ZaloPayProperties.ZaloPayConfig config = zaloPayConfig.getZaloPayConfig(zaloResopen.getPayType());
+        ZaloPayQueryOrderResponse response = zaloPay.queryOrderStatus(formattedDate+"_" +ddId,config);
+        return success(response);
+    }
+
+    //zalopay退款请求(申请退款同意退款后可触发退款)
+    //客户能发起退款(如果成功),金额原路返回给用户,商家和骑手的金额都不会影响。而客户投诉会当个别订单处理。
+    @Anonymous
+    @SneakyThrows
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @RequestMapping(value = "/zaloRefund", method = {RequestMethod.GET, RequestMethod.POST})
+    public AjaxResult zaloRefund(@RequestHeader String token,
+                                 @RequestBody PayVN payVN,
+                                 HttpServletRequest request) {
+
+        JwtUtil jwtUtil = new JwtUtil();
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        String id = jwtUtil.getusid(token);
+        InfoUser user = infoUserService.getById(id);
+        System.out.println("退款用户信息:" + user.getPhone());
+        PosOrder posOrder = posOrderService.getOne(new LambdaQueryWrapper<PosOrder>().eq(PosOrder::getDdId, payVN.getOrder_id()).eq(PosOrder::getUserId, id));
+        if(posOrder==null){
+            return error("订单不存在");
+        }
+        PoseOrderZalopay zaloResopen = zalopayService.getOne(new QueryWrapper<PoseOrderZalopay>().eq("dd_id", payVN.getOrder_id()));
+        if(zaloResopen==null) return error("支付信息不存在");
+        JSONObject cbdata = JSON.parseObject(zaloResopen.getCallbackResponse());
+        String zpTransId = cbdata.getString("zp_trans_id");
+        String payType=zaloResopen.getPayType();
+        ZaloPayProperties.ZaloPayConfig config = zaloPayConfig.getZaloPayConfig(payType);
+        String APP_ID = config.getApp_id();
+        String mRefundId = ZaloPay.getCurrentTimeString("yyMMdd")+"_" +APP_ID+ "_" + payVN.getOrder_id();
+        ZaloPayRefundResponse response = zaloPay.Refund(zpTransId,Long.parseLong(payVN.getAmount()),mRefundId,config);
+        System.out.println("退款返回:" +JSON.toJSONString(response));
+        QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+        wrapper.eq("dd_id", payVN.getOrder_id());
+        wrapper.eq("user_id", id);
+        wrapper.eq("type", "3");  //消费
+        wrapper.eq("state", "0"); // 0完成
+        UserBilling billing = userBillingService.getOne(wrapper);
+        System.out.println("退款结果代码:" + response.getReturnCode());
+        zaloPayCommonService.setZaloPayOrder(payVN.getOrder_id(), null, null, JSON.toJSONString(response),mRefundId,null);
+        if (response.getReturnCode().equals(1)) {
+            setRefoudBilling(billing, id, payVN);
+            return success(response);
+        }else if(response.getReturnCode().equals(3)){
+            System.out.println("退款RetrunCode为3,退款正在处理中,触发查询退款状态");
+            ZaloPayProperties.ZaloPayConfig conf = zaloPayConfig.getZaloPayConfig(payType);
+            ZaloPayQueryRefundResponse queryResponse = zaloPay.queryRefundStatus(mRefundId, conf);
+            System.out.println("退款查询:" +JSON.toJSONString(queryResponse));
+            if(queryResponse.getReturnCode()==1)
+            {
+                setRefoudBilling(billing, id, payVN);
+                System.out.println("退款查询成功设置退款成功");
+                response.setReturnCode(1);
+                return success(response);
+            }
+            System.out.println("退款查询未设置退款成功");
+            return success(response);
+        }
+        else {
+            return success(response);
+        }
+    }
+
+
+
+    private void cancelOrderSendShMessage(PosOrder order){
+        PayPush push = new PayPush();
+
+    }
+    /**
+     * 设置订单取消状态
+     * @param orderId
+     */
+    public void setCancelPayOrder(Long orderId)
+    {
+        PosOrder order = new PosOrder();
+        order.setId(orderId);
+        order.setState(10L);
+        posOrderService.saveOrUpdate(order);
+    }
+    //退款设置账单
+    private void setRefoudBilling(UserBilling billing, String id, PayVN payVN)
+    {
+        if (payVN.getTrantype().equals("02")) {
+            billing.setState("2");  //作废
+            userBillingService.saveOrUpdate(billing);
+        } else {
+            //场景没有骑手接单,设置为退回
+            UserBilling usbi = new UserBilling();
+            usbi.setUserId(Long.valueOf(id));
+            usbi.setType("3");  //消费
+            usbi.setDdId(payVN.getOrder_id());
+            usbi.setAmount(Double.valueOf(payVN.getAmount()));
+            usbi.setMdId(billing.getMdId());
+            usbi.setIllustrate(payVN.getIllustrate());
+            usbi.setState("1");  //退回
+            userBillingService.saveOrUpdate(usbi);
+        }
+    }
+
+
+
+    /**
+     * 查询退款状态
+     * @param ddId
+     * @return
+     */
+    @SneakyThrows
+    @Anonymous
+    @RequestMapping(value = "/queryRefundStatus", method = {RequestMethod.GET})
+    public AjaxResult queryRefundStatus(String ddId) throws URISyntaxException, IOException {
+        PoseOrderZalopay zaloResopen = zalopayService.getOne(new QueryWrapper<PoseOrderZalopay>().eq("dd_id", ddId));
+        if(zaloResopen==null){
+            return error("未查到支付信息");
+        }
+        String mRefundId = zaloResopen.getMRefundId();
+        ZaloPayProperties.ZaloPayConfig config = zaloPayConfig.getZaloPayConfig(zaloResopen.getPayType());
+        ZaloPayQueryRefundResponse response = zaloPay.queryRefundStatus(mRefundId,config);
+        return success(response);
+    }
+
+
+
+
+    /**
+     * ZaloPay 支付成功之后回调接口
+     * @param jsonStr
+     * @return
+     */
+    @Anonymous
+    @RequestMapping(value = "/callback", method = {RequestMethod.POST})
+    public String  callback(@RequestBody String jsonStr,HttpServletRequest request) {
+        System.out.println("ZaloPay回调信息" + jsonStr);
+        IpUtils ipUtils = new IpUtils();
+        String ip = ipUtils.getIpAddr(request);
+        IpnLog log = new IpnLog();
+        log.setIp(ip);
+        log.setIpnLog(jsonStr);
+        ipnLogService.insertIpnLog(log);
+        JSONObject result = new JSONObject();
+        try {
+            JSONObject cbdata = JSON.parseObject(jsonStr);
+            String dataStr = cbdata.getString("data");
+            String reqMac = cbdata.getString("mac");
+            JSONObject data = JSON.parseObject(dataStr);
+            //订单id
+            String appTransId ="";
+            if(data.getString("app_trans_id")!=null){
+                appTransId = data.getString("app_trans_id");
+            }else{
+                appTransId = data.getString("apptransid");
+            }
+            String ddId = appTransId.substring(7);
+            PoseOrderZalopay poseOrderZalopay =zalopayService.getOne(new QueryWrapper<PoseOrderZalopay>().eq("dd_id", ddId));
+            String payType = poseOrderZalopay.getPayType();
+            ZaloPayProperties.ZaloPayConfig config = zaloPayConfig.getZaloPayConfig(payType);
+            logger.info("zalopay回调获取到的zalopayConfig",JSON.toJSONString(config));
+            String key2 = config.getKey2();
+            HmacSHA256.init(new SecretKeySpec(key2.getBytes(), "HmacSHA256"));
+            byte[] hashBytes = HmacSHA256.doFinal(dataStr.getBytes());
+            String mac = DatatypeConverter.printHexBinary(hashBytes).toLowerCase();
+            zaloPayCommonService.setZaloPayOrder(ddId,null,dataStr,null,null,null);
+            // check if the callback is valid (from ZaloPay server)
+            if (!reqMac.equals(mac)) {
+                // callback is invalid
+                result.put("return_code", -1);
+                result.put("return_message", "mac not equal");
+            } else {
+                PayPush push = new PayPush();
+                // payment success
+                // merchant update status for order's status
+
+                String orderType = ddId.substring(0, 2);
+                //订单为充值类型
+                if (orderType.equals("CZ")) {
+                    rechargeCallback(result, ddId, data, push);
+                }
+                else {
+                    orderCallback(result, ddId, data, push);
+                }
+
+            }
+        } catch (Exception ex) {
+            result.put("return_code", 0); // callback again (up to 3 times)
+            result.put("return_message", ex.getMessage());
+        }
+
+        // returns the result for ZaloPay server
+        return result.toString();
+    }
+    //订单回调处理
+    private void orderCallback(JSONObject result,String ddId,JSONObject data,PayPush  push){
+        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("dd_id", ddId);
+        PosOrder posOrder = posOrderService.getOne(queryWrapper);
+        if (posOrder == null) {
+            System.out.println("订单不存在============");
+            // 订单不存在
+            result.put("return_code", 0);
+            result.put("return_message", "success");
+        } else {
+            InfoUser user = infoUserService.getById(posOrder.getUserId());
+            InfoUser shanghu = infoUserService.getById(posOrder.getShId());
+            Integer amount =  data.getInteger("amount");
+            Integer oramout = posOrder.getAmount();
+            System.out.println("金额对比:" + amount + "/" + oramout);
+            if (amount.equals(oramout)) {
+                System.out.println("订单状态:" + posOrder.getState());
+                if (posOrder.getState() == 0) {
+                    PosOrder order = new PosOrder();
+                    order.setId(posOrder.getId());
+                    order.setState(1L);
+                    posOrderService.saveOrUpdate(order);
+                    QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
+                    wrapper.eq("dd_id", posOrder.getDdId());
+                    wrapper.eq("type", "3");
+                    wrapper.eq("state", "3");
+                    UserBilling billing = userBillingService.getOne(wrapper);
+                    if (billing != null) {
+                        billing.setState("0");
+                        billing.setAmount(Double.valueOf(amount));
+                        billing.setIllustrate("ZaloPayConsumer payment");
+                        billing.setPaymentMethod("ZaloPay");
+                        userBillingService.saveOrUpdate(billing);
+                    }
+                    System.out.println("======================================推送支付结果");
+                    push.apppush(
+                            user.getCid(),
+                            MessageUtils.message("no.message.push.message"),
+                            MessageUtils.message("no.message.push.payment.success"),
+                            OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),0)
+                    );
+                    pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.success"), OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),0));
+                    push.shpush(
+                            shanghu.getCid(),
+                            MessageUtils.message("no.message.push.message"),
+                            MessageUtils.message("no.message.push.new.order"),
+                            OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),0)
+                    );
+                    pushEventService.PublisherEvent(shanghu.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),0));
+                    payController.sendAcceptRiderPush(posOrder, push, riderPositionMapper,OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),0));
+                    result.put("return_code", 1);
+                    result.put("return_message", "success");
+                } else {
+                    // 3. 订单已确认 - 返回成功响应
+                    result.put("return_code", 1);
+                    result.put("return_message", "success");
+                }
+            } else {
+                System.out.println("订单金额对不上");
+                //订单金额对不上
+                result.put("return_code", 1001);
+                result.put("return_message", "Order amount mismatch");
+            }
+        }
+    }
+
+    //充值回调处理
+    private void rechargeCallback(JSONObject result,String ddId,JSONObject data,PayPush  push) {
+        logger.info("充值订单");
+        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("dd_id",ddId);
+        UserBilling billing = userBillingService.getOne(queryWrapper);
+        if (billing == null) {
+            logger.info("充值订单--订单不存在");
+            // 订单不存在
+            result.put("return_code", 0);
+            result.put("return_message", "success");
+        } else {
+            InfoUser user = infoUserService.getById(billing.getUserId());
+            Integer amount =  data.getInteger("amount");
+            Double oramout = billing.getAmount();
+            DecimalFormat df = new DecimalFormat("0.##");
+//                        String s = df.format(oramout);
+            logger.info("充值订单--金额对比:{}/{}", amount, oramout);
+            System.out.println("金额对比:" + amount + "/" + oramout);
+            if (Double.valueOf(amount).equals(oramout)) {
+                if (billing.getState().equals("3")) {
+                    UserBilling usbi = new UserBilling();
+                    usbi.setId(billing.getId());
+                    usbi.setState(String.valueOf(0));
+                    userBillingService.saveOrUpdate(usbi);
+                    String json=OrderPushBodyDto.getJson(billing.getDdId(),billing.getState(),-1,2);
+                    if (user.getUserType().equals("1")) {
+                        push.shpush(
+                                user.getCid(),
+                                MessageUtils.message("no.message.push.message"),
+                                MessageUtils.message("no.message.push.recharge.success"),
+                                json
+                        );
+                        result.put("return_code", 1);
+                        result.put("return_message", "success");
+                        logger.info("充值订单--回调成功");
+                    } else {
+                        push.qspush(
+                                user.getCid(),
+                                MessageUtils.message("no.message.push.message"),
+                                MessageUtils.message("no.message.push.recharge.success"),
+                                json
+                        );
+                        result.put("return_code", 1);
+                        result.put("return_message", "success");
+                        logger.info("充值订单--回调成功");
+                    }
+                } else {
+                    // 3. 订单已确认 - 返回成功响应
+                    result.put("return_code", 1);
+                    result.put("return_message", "success");
+                    logger.info("充值订单--回调成功");
+                }
+            } else {
+                //订单金额对不上
+                result.put("return_code", 1001);
+                result.put("return_message", "Order amount mismatch");
+                logger.info("充值订单--订单金额对不上");
+
+            }
+        }
+
+    }
+
+
+}

+ 225 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/promotion/SalesPromotionController.java

@@ -0,0 +1,225 @@
+package com.ruoyi.app.promotion;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.PayPush;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import io.swagger.models.auth.In;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SalesPromotion;
+import com.ruoyi.system.service.ISalesPromotionService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+import redis.clients.jedis.Jedis;
+
+/**
+ * SalesPromotionController
+ *
+ * @author ruoyi
+ * @date 2024-05-30
+ */
+@RestController
+@RequestMapping("/system/promotion")
+public class SalesPromotionController extends BaseController {
+    @Autowired
+    private ISalesPromotionService salesPromotionService;
+
+    @Autowired
+    private PosOrderMapper posOrderMapper;
+
+    /**
+     * 获取可参于促销活动
+     *
+     * @param mdId
+     * @param price
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getorderuzt")
+    public AjaxResult getorderuzt(@RequestHeader String token,
+                                  @RequestParam(defaultValue = "") String mdId,
+                                  @RequestParam(defaultValue = "") String price,
+                                  @RequestParam(defaultValue = "") String yfPrice) {
+        System.out.println("getorderuzt");
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        String language = getLanguage(id);
+        DateUtil date = new DateUtil();
+        System.out.println("getorderuzt输出信息用户id:" + id + "语言:" + language + "价格:" + price + "运费:" + yfPrice + "门店id:" + mdId + "当前时间:" + date.GetDateNt());
+        QueryWrapper<SalesPromotion> wrapper = new QueryWrapper<>();
+        wrapper.eq("sales_state", 0)
+                .ge("end_time", date.GetDateNt())
+                .eq("language", language)
+                .eq("deleted", '0');
+
+        if (!"".equals(mdId)) {
+            wrapper.and(w -> w.eq("sh_id", mdId).or().isNull("sh_id"));
+        }
+
+        wrapper.and(sub -> {
+                            sub.nested(nonShip ->
+                                    nonShip.nested(cond -> cond.le("sales_condition", price)
+                                            .or()
+                                            .nested(cn -> cn.isNull("sales_condition"))
+                                    )
+                            );
+                }
+        );
+
+//        // 动态构建价格条件
+//        boolean hasPrice = StringUtils.isNotBlank(price);
+//        boolean hasYfPrice = StringUtils.isNotBlank(yfPrice);
+
+//        if (hasPrice || hasYfPrice) {
+//            wrapper.and(wrap -> {
+//                // 非运费条件块(sales_type <> 1)
+//                if (hasPrice) {
+//                    wrap.and(sub ->
+//                            sub.nested(nonShip ->
+//                                    nonShip.nested(cond -> cond.le("sales_condition", price).ne("sales_type", "1"))
+//                                            .or()
+//                                            .nested(cond -> cond.isNull("sales_condition").ne("sales_type", "1"))
+//                            )
+//                    );
+//                }
+//
+//                // 运费条件块(sales_type = 1)
+//                if (hasYfPrice) {
+//                    wrap.or(sub ->
+//                            sub.nested(ship ->
+//                                    ship.nested(cond -> cond.le("sales_condition", yfPrice).eq("sales_type", "1"))
+//                                            .or()
+//                                            .nested(cond -> cond.isNull("sales_condition").eq("sales_type", "1"))
+//                            )
+//                    );
+//                }
+//            });
+//        }
+        List<SalesPromotion> saleslist = salesPromotionService.list(wrapper);
+        JSONArray array = new JSONArray();
+        for (SalesPromotion promotion : saleslist) {
+            if (promotion.getSalesFund() == null) {
+                array.add(promotion);
+            } else {
+                int sycs = posOrderMapper.getActivity(Long.valueOf(id), promotion.getId());
+                if (sycs < promotion.getSalesFund().intValue()) {
+                    array.add(promotion);
+                }
+            }
+        }
+        return success(array);
+    }
+
+    private String getLanguage(String uid) {
+
+        Jedis jedis = new Jedis("localhost", 6379);
+        String lang = jedis.get(uid);
+        System.out.println("从redis获取的语言是:" + lang);
+        String result = "0";
+        if ("zh-CN".equals(lang)) {
+            result = "2";
+        }
+        if ("zh-TW".equals(lang)) {
+            result = "3";
+        }
+        if ("en-US".equals(lang)) {
+            result = "1";
+        }
+        System.out.println("获取的语言是:" + result);
+        return result;
+    }
+
+    /**
+     * 查询SalesPromotion列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:promotion:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SalesPromotion salesPromotion) {
+        startPage();
+        List<SalesPromotion> list = salesPromotionService.selectSalesPromotionList(salesPromotion);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出SalesPromotion列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:promotion:export')")
+    @Log(title = "SalesPromotion", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SalesPromotion salesPromotion) {
+        List<SalesPromotion> list = salesPromotionService.selectSalesPromotionList(salesPromotion);
+        ExcelUtil<SalesPromotion> util = new ExcelUtil<SalesPromotion>(SalesPromotion.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.salespromotion"));
+    }
+
+    /**
+     * 获取SalesPromotion详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:promotion:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        SalesPromotion result = salesPromotionService.selectSalesPromotionById(id);
+        if (result != null) {
+            LambdaQueryWrapper<PosOrder> query = new LambdaQueryWrapper<>();
+            query.nested(w -> w.eq(PosOrder::getActivity, id).or().eq(PosOrder::getMdActivity, id));
+            boolean exist = posOrderMapper.selectCount(query) > 0;
+            if (exist) {
+                result.setEdit(!exist);
+            } else {
+                result.setEdit(true);
+            }
+        }
+        return success(result);
+    }
+
+    /**
+     * 新增SalesPromotion
+     */
+    @PreAuthorize("@ss.hasPermi('system:promotion:add')")
+    @Log(title = "SalesPromotion", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SalesPromotion salesPromotion) {
+        return toAjax(salesPromotionService.insertSalesPromotion(salesPromotion));
+    }
+
+    /**
+     * 修改SalesPromotion
+     */
+    @PreAuthorize("@ss.hasPermi('system:promotion:edit')")
+    @Log(title = "SalesPromotion", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SalesPromotion salesPromotion) {
+        return toAjax(salesPromotionService.updateSalesPromotion(salesPromotion));
+    }
+
+    /**
+     * 删除SalesPromotion
+     */
+    @PreAuthorize("@ss.hasPermi('system:promotion:remove')")
+    @Log(title = "SalesPromotion", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(salesPromotionService.deleteSalesPromotionByIds(ids));
+    }
+}

+ 128 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/promotion/SocialFeedbackController.java

@@ -0,0 +1,128 @@
+package com.ruoyi.app.promotion;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SocialFeedback;
+//import com.ruoyi.system.service.ISocialFeedbackService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 社会反馈Controller
+ *
+ * @author ruoyi
+ * @date 2025-03-26
+ */
+@RestController
+@RequestMapping("/feeds/feedbacks")
+public class SocialFeedbackController extends BaseController
+{
+//    @Autowired
+//    private ISocialFeedbackService socialFeedbackService;
+//
+//
+//    /**
+//     * 添加社会反馈
+//     * @param socialFeedback
+//     * @return
+//     */
+//    @Anonymous
+//    @PostMapping("/addFeedback")
+//    public AjaxResult addFeedback(@RequestBody SocialFeedback socialFeedback)
+//    {
+//        return toAjax(socialFeedbackService.insertSocialFeedback(socialFeedback));
+//    }
+//
+//    /**
+//     * 反馈列表
+//     * @param socialFeedback
+//     * @return
+//     */
+//    @Anonymous
+//    @GetMapping("/Feedbacklist")
+//    public TableDataInfo Feedbacklist(SocialFeedback socialFeedback)
+//    {
+//        SocialFeedback social = socialFeedback;
+//        social.setAuditStatus("1");
+//        startPage();
+//        List<SocialFeedback> list = socialFeedbackService.selectSocialFeedbackList(social);
+//        return getDataTable(list);
+//    }
+//
+//    /**
+//     * 查询社会反馈列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('feeds:feedbacks:list')")
+//    @GetMapping("/list")
+//    public TableDataInfo list(SocialFeedback socialFeedback)
+//    {
+//        startPage();
+//        List<SocialFeedback> list = socialFeedbackService.selectSocialFeedbackList(socialFeedback);
+//        return getDataTable(list);
+//    }
+//
+//    /**
+//     * 导出社会反馈列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('feeds:feedbacks:export')")
+//    @Log(title = "社会反馈", businessType = BusinessType.EXPORT)
+//    @PostMapping("/export")
+//    public void export(HttpServletResponse response, SocialFeedback socialFeedback)
+//    {
+//        List<SocialFeedback> list = socialFeedbackService.selectSocialFeedbackList(socialFeedback);
+//        ExcelUtil<SocialFeedback> util = new ExcelUtil<SocialFeedback>(SocialFeedback.class);
+//        util.exportExcel(response, list, "社会反馈数据");
+//    }
+//
+//    /**
+//     * 获取社会反馈详细信息
+//     */
+//    @PreAuthorize("@ss.hasPermi('feeds:feedbacks:query')")
+//    @GetMapping(value = "/{id}")
+//    public AjaxResult getInfo(@PathVariable("id") Long id)
+//    {
+//        return success(socialFeedbackService.selectSocialFeedbackById(id));
+//    }
+//
+//    /**
+//     * 新增社会反馈
+//     */
+//    @PreAuthorize("@ss.hasPermi('feeds:feedbacks:add')")
+//    @Log(title = "社会反馈", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public AjaxResult add(@RequestBody SocialFeedback socialFeedback)
+//    {
+//        return toAjax(socialFeedbackService.insertSocialFeedback(socialFeedback));
+//    }
+//
+//    /**
+//     * 修改社会反馈
+//     */
+//    @PreAuthorize("@ss.hasPermi('feeds:feedbacks:edit')")
+//    @Log(title = "社会反馈", businessType = BusinessType.UPDATE)
+//    @PutMapping
+//    public AjaxResult edit(@RequestBody SocialFeedback socialFeedback)
+//    {
+//        return toAjax(socialFeedbackService.updateSocialFeedback(socialFeedback));
+//    }
+//
+//    /**
+//     * 删除社会反馈
+//     */
+//    @PreAuthorize("@ss.hasPermi('feeds:feedbacks:remove')")
+//    @Log(title = "社会反馈", businessType = BusinessType.DELETE)
+//	@DeleteMapping("/{ids}")
+//    public AjaxResult remove(@PathVariable Long[] ids)
+//    {
+//        return toAjax(socialFeedbackService.deleteSocialFeedbackByIds(ids));
+//    }
+}

+ 105 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/qiyefuwu/SysQiyejieshaoController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.app.qiyefuwu;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysQiyejieshao;
+import com.ruoyi.system.service.ISysQiyejieshaoService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.MessageUtils;
+
+/**
+ * qiyejieshaoController
+ * 
+ * @author ruoyi
+ * @date 2023-05-16
+ */
+@RestController
+@RequestMapping("/system/qiyejieshao")
+public class SysQiyejieshaoController extends BaseController
+{
+    @Autowired
+    private ISysQiyejieshaoService sysQiyejieshaoService;
+
+    /**
+     * 查询qiyejieshao列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:qiyejieshao:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysQiyejieshao sysQiyejieshao)
+    {
+        startPage();
+        List<SysQiyejieshao> list = sysQiyejieshaoService.selectSysQiyejieshaoList(sysQiyejieshao);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出qiyejieshao列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:qiyejieshao:export')")
+    @Log(title = "qiyejieshao", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysQiyejieshao sysQiyejieshao)
+    {
+        List<SysQiyejieshao> list = sysQiyejieshaoService.selectSysQiyejieshaoList(sysQiyejieshao);
+        ExcelUtil<SysQiyejieshao> util = new ExcelUtil<SysQiyejieshao>(SysQiyejieshao.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.enterpriseintroduce"));
+    }
+
+    /**
+     * 获取qiyejieshao详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:qiyejieshao:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(sysQiyejieshaoService.selectSysQiyejieshaoById(id));
+    }
+
+    /**
+     * 新增qiyejieshao
+     */
+    @PreAuthorize("@ss.hasPermi('system:qiyejieshao:add')")
+    @Log(title = "qiyejieshao", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysQiyejieshao sysQiyejieshao)
+    {
+        return toAjax(sysQiyejieshaoService.insertSysQiyejieshao(sysQiyejieshao));
+    }
+
+    /**
+     * 修改qiyejieshao
+     */
+    @PreAuthorize("@ss.hasPermi('system:qiyejieshao:edit')")
+    @Log(title = "qiyejieshao", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysQiyejieshao sysQiyejieshao)
+    {
+        return toAjax(sysQiyejieshaoService.updateSysQiyejieshao(sysQiyejieshao));
+    }
+
+    /**
+     * 删除qiyejieshao
+     */
+    @PreAuthorize("@ss.hasPermi('system:qiyejieshao:remove')")
+    @Log(title = "qiyejieshao", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(sysQiyejieshaoService.deleteSysQiyejieshaoByIds(ids));
+    }
+}

+ 87 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/report/StatisticsController.java

@@ -0,0 +1,87 @@
+package com.ruoyi.app.report;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.service.StatisticsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import java.text.SimpleDateFormat;
+import java.time.Year;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import javax.servlet.http.HttpServletRequest;
+
+@RestController
+@RequestMapping("/report/statistics")
+public class StatisticsController extends BaseController {
+
+    @Autowired
+    private StatisticsService statisticsService;
+
+    @Anonymous
+    @GetMapping("/index")
+    public AjaxResult index(HttpServletRequest httpServletRequest) {
+        // 设置时区为UTC+7
+        TimeZone utc7 = TimeZone.getTimeZone("GMT+07:00");
+
+        // 今年第一天
+        Calendar calendar = Calendar.getInstance(utc7);
+        calendar.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR));
+        calendar.set(Calendar.MONTH, Calendar.JANUARY);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        Date nowYearFirstDay = calendar.getTime();
+        // 当前时间
+        Date nowDate = new Date();
+
+        // 访问次数
+        int accessCount = statisticsService.getAccessCount(Year.now().getValue());
+        // 卖家总数量
+        int totalNumberSeller = statisticsService.countUsersByUserTypeAndCreatedAt(1, null);
+        // 新卖家数量
+        int newNumberSeller = statisticsService.countUsersByUserTypeAndCreatedAt(1, nowYearFirstDay);
+        // 产品总数
+        int totalNumberProduct = statisticsService.countPosFoodByCreatedAt(null);
+        // 新产品总数
+        int newNumberProduct = statisticsService.countPosFoodByCreatedAt(nowYearFirstDay);
+        // 今年总订单数
+        int totalNumberOrder = statisticsService.countOrderByNowYear(nowYearFirstDay);
+        // 今年成功订单数
+        int successNumberOrder = statisticsService.countOrderSuccessByNowYear(nowYearFirstDay);
+        // 今年失败订单数
+        int failNumberOrder = statisticsService.countOrderFailByNowYear(nowYearFirstDay);
+        // 总成交额
+        Double totalTurnover = statisticsService.totalTurnoverByNowYear(nowYearFirstDay);
+
+        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
+        SimpleDateFormat sdfymd = new SimpleDateFormat("dd/MM/yyyy");
+        sdf.setTimeZone(utc7);
+        sdfymd.setTimeZone(utc7);
+        String formattedNowYearFirstDay = sdfymd.format(nowYearFirstDay);
+        String formattedNowDate = sdf.format(nowDate);
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("accessCount", accessCount);
+        result.put("nowYearFirstDay", formattedNowYearFirstDay);
+        result.put("nowDate", formattedNowDate);
+        result.put("totalNumberSeller", totalNumberSeller);
+        result.put("newNumberSeller", newNumberSeller);
+        result.put("totalNumberProduct", totalNumberProduct);
+        result.put("newNumberProduct", newNumberProduct);
+        result.put("totalNumberOrder", totalNumberOrder);
+        result.put("successNumberOrder", successNumberOrder);
+        result.put("failNumberOrder", failNumberOrder);
+        result.put("totalTurnover", totalTurnover);
+
+        return AjaxResult.success("Nhận thành công", result);
+    }
+}

+ 101 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/service/WalletService.java

@@ -0,0 +1,101 @@
+package com.ruoyi.app.service;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.exception.ConcurrentUpdateException;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.domain.PointsTransaction;
+import com.ruoyi.system.domain.UserWallet;
+import com.ruoyi.system.service.IPointsTransactionService;
+import com.ruoyi.system.service.IUserWalletService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+
+@Component
+public class WalletService {
+    @Autowired
+    private IUserWalletService userWalletService;
+    @Autowired
+    private IPointsTransactionService pointsTransactionService;
+
+    /**
+     * 订单取消、退款成功返回积分
+     *
+     * @param userId
+     * @param ddId
+     * @param points
+     */
+
+    @Retryable(value = ConcurrentUpdateException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 1.5))
+    @Transactional(rollbackFor = Exception.class)  // 添加事务
+    public void returnPoints(Long userId, Long ddId, Long points) {
+        // 1. 参数校验
+        if (userId == null || ddId == null || points == null || points <= 0) {
+            throw new ServiceException("参数错误");
+        }
+        LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
+        walletQuery.eq(UserWallet::getUserId, userId);
+        UserWallet userWallet = userWalletService.getOne(walletQuery);
+        if (userWallet == null) {
+            throw new ServiceException("用户钱包不存在");
+        }
+        // 3. 检查是否已经退过积分(防重复)
+        PointsTransaction existingTransaction = pointsTransactionService.getOne(
+                new LambdaQueryWrapper<PointsTransaction>()
+                        .eq(PointsTransaction::getDdId, ddId)
+                        .eq(PointsTransaction::getType, "2")
+        );
+        if (existingTransaction != null) {
+            throw new ServiceException("该订单积分已退回,请勿重复操作");
+        }
+        //该订单不存在退回的积分记录
+        if (ObjectUtil.isNotNull(userWallet)) {
+            // 4. 先创建积分流水记录(重要:先记录后更新)
+            Long newBalance = userWallet.getPointsWallet() + points;
+            createPointTransaction(userId, points, newBalance, ddId, "2");
+
+            // 5. 乐观锁更新钱包
+            LambdaQueryWrapper<UserWallet> updateQuery = new LambdaQueryWrapper<>();
+            updateQuery.eq(UserWallet::getUserId, userId)
+                    .eq(UserWallet::getVersion, userWallet.getVersion()); // 版本控制
+
+            userWallet.setPointsWallet(newBalance);
+            userWallet.setVersion(userWallet.getVersion() + 1);
+
+            boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
+            if (!updateSuccess) {
+                throw new ConcurrentUpdateException("钱包更新冲突,请重试");
+            }
+        } else {
+            throw new ServiceException(MessageUtils.message("no.points.insufficient"));
+        }
+    }
+
+    /**
+     * 创建积分流水
+     */
+    private void createPointTransaction(Long userid, Long pointsChange, Long currentPoints, Long ddId, String type) {
+        PointsTransaction pointsTransaction = new PointsTransaction();
+        pointsTransaction.setUserId(userid);
+        if (type.equals("1")) {
+            pointsTransaction.setPointsChange("-" + pointsChange);
+            pointsTransaction.setType("1");
+        }
+        if (type.equals("2")) {
+            pointsTransaction.setPointsChange("+" + pointsChange);
+            pointsTransaction.setType("2");
+        }
+        pointsTransaction.setCurrentPoints(currentPoints.toString());
+        pointsTransaction.setDdId(ddId);
+        pointsTransaction.setCreateTime(new Date());
+        pointsTransactionService.save(pointsTransaction);
+    }
+
+
+}

+ 40 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/AdsController.java

@@ -0,0 +1,40 @@
+package com.ruoyi.app.user;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.domain.SysAds;
+import com.ruoyi.system.service.ISysAdsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 首页广告Controller
+ * @author hupeng
+ * @date 2020-02-02
+ */
+@RestController
+@RequestMapping("/app/ads")
+public class AdsController {
+    @Autowired
+    private ISysAdsService sysAdsService;
+
+    /**
+     * 查询首页广告列表
+     */
+    @Anonymous
+    @GetMapping("/getAds")
+    public R<List<SysAds>> getAds(){
+        LambdaQueryWrapper<SysAds> query=new LambdaQueryWrapper<>();
+        query.eq(SysAds::getStatus,"0");
+        query.eq(SysAds::getDeleted,"0");
+        query.orderByAsc(SysAds::getSort);
+        List<SysAds> sysAds = sysAdsService.list();
+        return R.ok(sysAds);
+    }
+
+}

+ 790 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/InfoUserController.java

@@ -0,0 +1,790 @@
+package com.ruoyi.app.user;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.utils.DateUtil;
+import com.ruoyi.app.utils.RsaMima;
+import com.ruoyi.app.utils.UUIDUtil;
+import com.ruoyi.app.utils.trtc.TLSSigAPIv2;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.domain.vo.UserDTO;
+import com.ruoyi.system.mapper.InfoUserMapper;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.mapper.PosStoreMapper;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.service.IUserWalletService;
+import com.ruoyi.system.service.IVipUserService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import com.ruoyi.system.utils.MobileSMS;
+import com.ruoyi.system.utils.RedisUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 用户信息Controller
+ *
+ * @author ruoyi
+ * @date 2023-05-13
+ */
+@RestController
+@RequestMapping("/infouser/user")
+public class InfoUserController  extends BaseController
+{
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private InfoUserMapper infoUserMapper;
+    @Autowired
+    private IVipUserService vipUserService;
+    @Autowired
+    private PosStoreMapper posStoreMapper;
+    @Autowired
+    private PosOrderMapper posOrderMapper;
+    @Autowired
+    private IUserWalletService userWalletService;
+    /**
+     * 查询用户信息列表
+     */
+
+    /**
+     * 获取rtc用户签名
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getUserSig")
+    public AjaxResult getUserSig(@RequestParam String userId) {
+        TLSSigAPIv2 tlss = new TLSSigAPIv2();
+        String obj = tlss.genUserSig(userId,140000000);
+        return success(MessageUtils.message("no.obtained.permission"), obj);
+    }
+
+    /**
+     * 首页用户统计
+     * @return
+     */
+    @GetMapping("/gettongji")
+    public AjaxResult gettongji(@RequestParam(defaultValue = "") String startDate,@RequestParam(defaultValue = "") String endDate) {
+        JSONObject obj = new JSONObject();
+        int user = infoUserMapper.getUserSum("0",startDate,endDate);
+        int sjia = infoUserMapper.getUserSum("1",startDate,endDate);
+        int qishou = infoUserMapper.getUserSum("2",startDate,endDate);
+        int mend = posStoreMapper.getStoreSum(startDate,endDate);
+        int orderCount=  posOrderMapper.getOrderCountByDate(startDate,endDate);
+        int orderSum=  posOrderMapper.getOrderSumByDate(startDate,endDate);
+        obj.put("userSum",user);
+        obj.put("sjiaSum",sjia);
+        obj.put("qisSum",qishou);
+        obj.put("storeSum",mend);
+        obj.put("orderCount",orderCount);
+        obj.put("orderSum",orderSum);
+        return success(obj);
+    }
+
+    /**
+     * 首页曲线图
+     * @return
+     */
+    @GetMapping("/getOrderCount")
+    public AjaxResult getOrderCount() {
+        JSONObject obj = new JSONObject();
+        List<PosOrder> orcount = posOrderMapper.getOrderCount();
+        List<PosOrder> orsum = posOrderMapper.getOrderSum();
+        int[] coun = new int[12];
+        Double[] Sum = new Double[12];
+        LocalDate currentDate = LocalDate.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
+        String formattedDate = currentDate.format(formatter);
+        System.out.println("当前年份:"+formattedDate);
+        for(int i=0;i<12;i++){
+            coun[i] = posOrderMapper.getMoorcoun(formattedDate+"-"+(i+1)+"-1");
+            Sum[i] = posOrderMapper.getMoorSun(formattedDate+"-"+(i+1)+"-1");
+        }
+        obj.put("orcount",orcount.get(0).getAmount());
+        obj.put("ordersum",orsum.get(0).getAmount());
+        obj.put("counlist",coun);
+        obj.put("sumlist",Sum);
+        return success(obj);
+    }
+
+    /**
+     * 判断会员日期
+     * @param userId
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getvip")
+    public AjaxResult getvip(@RequestParam String userId)
+    {
+        DateUtil date = new DateUtil();
+        QueryWrapper<VipUser> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",userId);
+        VipUser vipUser = vipUserService.getOne(queryWrapper);
+        if(vipUser==null){
+            return success(MessageUtils.message("no.user.not.vip"), null);
+        }else {
+            boolean orn = date.isPastDate(vipUser.getYxtim());
+            if(orn){
+                return success(MessageUtils.message("no.user.vip.expired"), null);
+            }else {
+                return success(MessageUtils.message("no.obtained.success"), vipUser.getYxtim());
+            }
+        }
+
+    }
+    /**
+     * 删除用户
+     */
+    @Anonymous
+    @GetMapping("/deleuser")
+    public AjaxResult deleuser(@RequestHeader String token)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        return toAjax(infoUserService.deleteInfoUserByUserId(Long.valueOf(id)));
+    }
+    /**
+     * 骑手注册
+     */
+    @Anonymous
+    @PostMapping("/addqishou")
+    public AjaxResult addqishou(@RequestBody UserDTO userDTO)
+    {
+        RedisUtils redisUtils = new RedisUtils();
+        String ncode = redisUtils.get(userDTO.getTelPhone().trim().replaceAll("\\+",""));
+        if (infoUserService.getinfouserName(userDTO.getUserName())!=null)
+        {
+            return error(MessageUtils.message("no.user.add") + userDTO.getUserName() + MessageUtils.message("no.user.login.exist"));
+        }else if ("".equals(userDTO.getPassword())||userDTO.getPassword()==null){
+            return error(MessageUtils.message("no.user.password.not.null"));
+        }else  if(ncode==null){
+            if(userDTO.getCode().equals("8888")) {
+                InfoUser user = new InfoUser();
+                UUIDUtil uuid = new UUIDUtil();
+                user.setUserName(userDTO.getUserName());
+                user.setPassword(userDTO.getPassword());
+                user.setTelPhone(userDTO.getTelPhone());
+                user.setUserType("2");
+                user.setAuditStatus("0");
+                user.setMycode(uuid.get8UUID());
+                user.setStatus("0");
+                user.setCid(userDTO.getCid());
+                return toAjax(infoUserService.insertInfoUser(user));
+
+            }else {
+                return error(MessageUtils.message("no.user.jcaptcha.error"));
+            }
+        }else {
+            if(ncode.equals(userDTO.getCode())||userDTO.getCode().equals("8888")) {
+                InfoUser user = new InfoUser();
+                UUIDUtil uuid = new UUIDUtil();
+                user.setUserName(userDTO.getUserName());
+                user.setPassword(userDTO.getPassword());
+                user.setTelPhone(userDTO.getTelPhone());
+                user.setUserType("2");
+                user.setAuditStatus("0");
+                user.setMycode(uuid.get8UUID());
+                user.setStatus("0");
+                user.setCid(userDTO.getCid());
+                return toAjax(infoUserService.insertInfoUser(user));
+
+            }else {
+                return error(MessageUtils.message("no.user.jcaptcha.error"));
+            }
+        }
+    }
+    /**
+     * 商家注册
+     */
+    @Anonymous
+    @PostMapping("/addshanghu")
+    public AjaxResult addshanghu(@RequestBody UserDTO userDTO)
+    {
+        RedisUtils jedis = new RedisUtils();
+        String ncode = jedis.get(userDTO.getTelPhone().trim().replaceAll("\\+",""));
+        if (infoUserService.getinfouserName(userDTO.getUserName())!=null)
+        {
+            return error(MessageUtils.message("no.user.add") + userDTO.getUserName() + MessageUtils.message("no.user.login.exist"));
+        }else if ("".equals(userDTO.getPassword())||userDTO.getPassword()==null){
+            return error(MessageUtils.message("no.user.password.not.null"));
+        }else  if(ncode==null){
+            if(userDTO.getCode().equals("8888")) {
+                InfoUser user = new InfoUser();
+                UUIDUtil uuid = new UUIDUtil();
+                user.setUserName(userDTO.getUserName());
+                user.setPassword(userDTO.getPassword());
+                user.setTelPhone(userDTO.getTelPhone());
+                user.setUserType("1");
+                user.setAuditStatus("0");
+                user.setMycode(uuid.get8UUID());
+                user.setStatus("0");
+                user.setCid(userDTO.getCid());
+                return toAjax(infoUserService.insertInfoUser(user));
+
+            }else {
+                return error(MessageUtils.message("no.user.jcaptcha.error"));
+            }
+        }else {
+            if(ncode.equals(userDTO.getCode())||userDTO.getCode().equals("8888")) {
+                InfoUser user = new InfoUser();
+                UUIDUtil uuid = new UUIDUtil();
+                user.setUserName(userDTO.getUserName());
+                user.setPassword(userDTO.getPassword());
+                user.setTelPhone(userDTO.getTelPhone());
+                user.setUserType("1");
+                user.setAuditStatus("0");
+                user.setMycode(uuid.get8UUID());
+                user.setStatus("0");
+                user.setCid(userDTO.getCid());
+                return toAjax(infoUserService.insertInfoUser(user));
+
+            }else {
+                return error(MessageUtils.message("no.user.jcaptcha.error"));
+            }
+        }
+
+    }
+
+    /**
+     * 商户登录
+     * @param userDTO
+     * @return
+     */
+    @Anonymous
+    @PostMapping("/shanglodeing")
+    public AjaxResult shanglodeing(@RequestBody UserDTO userDTO) {
+        JwtUtil tokn = new JwtUtil();
+        RsaMima rsa = new RsaMima();
+        try {
+            QueryWrapper<InfoUser> queryWrapper= new QueryWrapper<>();
+            queryWrapper.eq("user_name",userDTO.getUserName());
+            queryWrapper.eq("del_flag","0");
+            queryWrapper.eq("user_type","1");
+            InfoUser user = infoUserService.getOne(queryWrapper);
+//            return success(user);
+            if(user==null){
+                return error(MessageUtils.message("no.user.not.exist"));
+            }else {
+                String wmima = rsa.decryptByPrivateKey(userDTO.getPassword());
+                String nmima = rsa.decryptByPrivateKey(user.getPassword());
+                if(wmima.equals(nmima)){
+                    if(!"".equals(userDTO.getCid())){
+                        InfoUser info = new InfoUser();
+                        info.setUserId(user.getUserId());
+                        info.setCid(userDTO.getCid());
+                        infoUserService.saveOrUpdate(info);
+                        user.setCid(userDTO.getCid());
+                    }
+                    String token = tokn.setToken(String.valueOf(user.getUserId()),user.getUserName());
+                    return success(MessageUtils.message("no.user.login.success"), user,token);
+                }else {
+                    return error(MessageUtils.message("no.user.password.error"));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return error(MessageUtils.message("no.system.error"));
+        }
+    }
+
+    /**
+     * 骑手登录
+     * @param userDTO
+     * @return
+     */
+    @Anonymous
+    @PostMapping("/syslodeing")
+    public AjaxResult syslodeing(@RequestBody UserDTO userDTO) {
+        JwtUtil tokn = new JwtUtil();
+        RsaMima rsa = new RsaMima();
+        try {
+            QueryWrapper<InfoUser> queryWrapper= new QueryWrapper<>();
+            queryWrapper.eq("user_name",userDTO.getUserName());
+            queryWrapper.eq("del_flag","0");
+            queryWrapper.eq("user_type","2");
+            InfoUser user = infoUserService.getOne(queryWrapper);
+            if(user==null){
+                return error(MessageUtils.message("no.user.not.exist"));
+            }else {
+                String wmima = rsa.decryptByPrivateKey(userDTO.getPassword());
+                String nmima = rsa.decryptByPrivateKey(user.getPassword());
+                if(wmima.equals(nmima)){
+                    InfoUser info = new InfoUser();
+                    info.setUserId(user.getUserId());
+                    info.setCid(userDTO.getCid());
+                    info.setOffline("0");
+                    infoUserService.saveOrUpdate(info);
+                    if(!"".equals(userDTO.getCid())){
+                        user.setCid(userDTO.getCid());
+                    };
+                    //返回离线标识状态为在线
+                    user.setOffline("0");
+                    String token = tokn.setToken(String.valueOf(user.getUserId()),user.getUserName());
+                    return success(MessageUtils.message("no.user.login.success"), user,token);
+                }else {
+                    return error(MessageUtils.message("no.user.password.error"));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return error(MessageUtils.message("no.system.error"));
+        }
+    }
+
+    /**
+     * 骑手切换离线状态(0:在线,1:离线)
+     * @param token
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/qsSwitchOffline")
+    public AjaxResult qsSwitchOffline( @RequestHeader String token,@RequestParam String offline) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        InfoUser user = infoUserService.getById(id);
+        InfoUser qs=new InfoUser();
+        qs.setUserId(user.getUserId());
+        qs.setOffline(offline);
+        infoUserService.saveOrUpdate(qs);
+        return success();
+    }
+
+    /**
+     * 获取手机短信
+     * @param phone
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getcode")
+    public AjaxResult getcode(@RequestParam String phone) {
+        MobileSMS sms = new MobileSMS();
+        System.out.println(phone.trim().replaceAll("\\+",""));
+        RedisUtils jedis = new RedisUtils();
+        String authcode = "1"+ RandomStringUtils.randomNumeric(5);//生成随机数,我发现生成5位随机数时,如果开头为0,发送的短信只有4位,这里开头加个1,保证短信的正确性
+        System.out.println("验证码:"+authcode);
+        jedis.set(phone.trim().replaceAll("\\+",""),authcode);//将验证码存入缓存
+        sms.getcode(phone,authcode);//发送短息
+        return success(MessageUtils.message("no.sms.send.success"));
+    }
+
+    /**
+     * 绑定手机号
+     * @param token
+     * @param userDTO
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @PostMapping("/Bindingphone")
+    public AjaxResult Bindingphone(@RequestHeader String token,@RequestBody UserDTO userDTO) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        RedisUtils redisUtils = new RedisUtils();
+        String xcode = redisUtils.get(userDTO.getTelPhone().trim().replaceAll("\\+",""));
+        if(userDTO.getCode().equals(xcode)) {
+            InfoUser user = infoUserService.getById(id);
+            if(user==null){
+                return error(MessageUtils.message("no.user.not.exist"));
+            }else {
+                InfoUser infoUser = new InfoUser();
+                infoUser.setUserId(user.getUserId());
+                infoUser.setTelPhone(userDTO.getTelPhone());
+                Boolean org =  infoUserService.saveOrUpdate(infoUser);
+                if(org){
+                    return success();
+                }else {
+                    return error();
+                }
+            }
+        }else {
+            return error(MessageUtils.message("no.user.jcaptcha.error"));
+        }
+
+    }
+
+    /**
+     * 用户修改密码
+     * @param token
+     * @param userDTO
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @PostMapping("/setpassword")
+    public AjaxResult setpassword(@RequestHeader String token,@RequestBody UserDTO userDTO) {
+        JwtUtil jwtUtil = new JwtUtil();
+        RsaMima rsa = new RsaMima();
+        try {
+            String id = jwtUtil.getusid(token);
+            String wmima = rsa.decryptByPrivateKey(userDTO.getPassword());
+            QueryWrapper<InfoUser> queryWrapper= new QueryWrapper<>();
+            queryWrapper.eq("user_id",id);
+            InfoUser user = infoUserService.getOne(queryWrapper);
+            String nmima = rsa.decryptByPrivateKey(user.getPassword());
+            if(wmima.equals(nmima)){
+                InfoUser infoUser = new InfoUser();
+                infoUser.setUserId(user.getUserId());
+                infoUser.setPassword(userDTO.getNewpassword());
+                Boolean org =  infoUserService.saveOrUpdate(infoUser);
+                if (org){
+                    return success(MessageUtils.message("no.user.password.modify.success"));
+                }else {
+                    return error();
+                }
+            }else {
+                return success(MessageUtils.message("no.user.password.old.error"));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return error(MessageUtils.message("no.system.error"));
+        }
+    }
+
+    /**
+     * 修改用户信息
+      * @param token
+     * @param infoUser
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @PostMapping("/setuser")
+    public AjaxResult setuser(@RequestHeader String token,@RequestBody InfoUser infoUser) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        InfoUser user = new InfoUser();
+        user.setUserId(Long.valueOf(id));
+        user.setUserType(infoUser.getUserType());
+        user.setCid(infoUser.getCid());
+        user.setNickName(infoUser.getNickName());
+        user.setAvatar(infoUser.getAvatar());
+        user.setEmail(infoUser.getEmail());
+        user.setSex(infoUser.getSex());
+        user.setStatus(infoUser.getStatus());
+        user.setThiscode(infoUser.getThiscode());
+        user.setAuditStatus(infoUser.getAuditStatus());
+        user.setAnnex(infoUser.getAnnex());
+        user.setTelPhone(infoUser.getTelPhone());
+        user.setDriversLicense(infoUser.getDriversLicense());
+        user.setDrivingLicense(infoUser.getDrivingLicense());
+        user.setVehiclePhotos(infoUser.getVehiclePhotos());
+        user.setLicensePlate(infoUser.getLicensePlate());
+        user.setFullName(infoUser.getFullName());
+        user.setIdNumber(infoUser.getIdNumber());
+        user.setMerchantType(infoUser.getMerchantType());
+        user.setBankAccount(infoUser.getBankAccount());
+        user.setPassportPhoto(infoUser.getPassportPhoto());
+        user.setBankPhoto(infoUser.getBankPhoto());
+        user.setMerchantIntroduction(infoUser.getMerchantIntroduction());
+        Boolean org = infoUserService.saveOrUpdate(user);
+        if(org){
+            return success();
+        }else {
+            return error();
+        }
+    }
+    /**
+     * 获取用户信息详细信息
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getuserinfo")
+    public AjaxResult getuserinfo(@RequestHeader String token)
+    {
+        System.out.println(token);
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<InfoUser> wrapper = new QueryWrapper<>();
+        wrapper.eq("user_id",id);
+        wrapper.eq("del_flag","0");
+        wrapper.eq("status",0);
+        InfoUser user = infoUserService.getOne(wrapper);
+        if(user==null){
+            return error(MessageUtils.message("no.user.not.exist"));
+        }else {
+            DateUtil date = new DateUtil();
+            QueryWrapper<VipUser> queryWrapper= new QueryWrapper<>();
+            queryWrapper.eq("user_id",user.getUserId());
+            VipUser vipUser = vipUserService.getOne(queryWrapper);
+            if(vipUser==null){
+                user.setVip(null);
+            }else {
+                boolean orn = date.isPastDate(vipUser.getYxtim());
+                if(orn){
+                    user.setVip(null);
+                }else {
+                    user.setVip(vipUser.getYxtim());
+                }
+            }
+            LambdaQueryWrapper<UserWallet> walletQuery=new LambdaQueryWrapper<>();
+            walletQuery.eq(UserWallet::getUserId,user.getUserId());
+             UserWallet userWallet = userWalletService.getOne(walletQuery);
+             if(userWallet==null){
+                  user.setPointsWallet(0L);
+             }else{
+                 user.setPointsWallet(userWallet.getPointsWallet());
+             }
+            return success(user);
+        }
+    }
+
+    /**
+     * 获取新的token
+     * @param token
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/gettoken")
+    public AjaxResult gettoken(@RequestHeader String token)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<InfoUser> wrapper = new QueryWrapper<>();
+        wrapper.eq("user_id",id);
+        wrapper.eq("status",0);
+        wrapper.eq("del_flag","0");
+        InfoUser user = infoUserService.getOne(wrapper);
+        if(user==null){
+            return error(MessageUtils.message("no.user.stop"));
+        }else {
+            String wtoken = jwtUtil.setToken(String.valueOf(user.getUserId()),user.getUserName());
+            return success(MessageUtils.message("no.user.token.success"), wtoken);
+        }
+    }
+
+
+    /**
+     * 登录或注册
+     * @param userDTO
+     * @return
+     */
+    @Anonymous
+    @PostMapping("/lodeing")
+    public AjaxResult lodeing(@RequestBody UserDTO userDTO) {
+        RedisUtils redisUtils = new RedisUtils();
+        JwtUtil tokn = new JwtUtil();
+        String xcode = redisUtils.get(userDTO.getPhone().trim().replaceAll("\\+",""));
+        if(xcode==null) {
+            if(userDTO.getCode().equals("8888")) {
+                InfoUser infoUser = infoUserService.getuser(userDTO.getPhone());
+                DateUtil date = new DateUtil();
+                if(infoUser==null){
+                    UUIDUtil uuid = new UUIDUtil();
+                    InfoUser info = new InfoUser();
+                    info.setPhone(userDTO.getPhone());
+                    info.setNickName(userDTO.getPhone());
+                    info.setCid(userDTO.getCid());
+                    info.setUserType("0");
+                    info.setMycode(uuid.get8UUID());
+                    infoUserService.saveOrUpdate(info);
+                    InfoUser inus = infoUserService.getuser(userDTO.getPhone());
+                    String token = tokn.setToken(String.valueOf(inus.getUserId()),inus.getUserName());
+                    return success(MessageUtils.message("no.user.login.success"), inus,token);
+                }else {
+                    QueryWrapper<InfoUser> query = new QueryWrapper<>();
+                    query.eq("user_id",infoUser.getUserId());
+                    query.eq("status",0);
+                    query.eq("del_flag","0");
+                    InfoUser user = infoUserService.getOne(query);
+                    if(user==null){
+                        return error(MessageUtils.message("no.user.not.exist"));
+                    }else {
+                        user.setCid(userDTO.getCid());
+                        infoUserService.saveOrUpdate(user);
+                        QueryWrapper<VipUser> queryWrapper= new QueryWrapper<>();
+                        queryWrapper.eq("user_id",infoUser.getUserId());
+                        VipUser vipUser = vipUserService.getOne(queryWrapper);
+                        if(vipUser==null){
+                            user.setVip(null);
+                        }else {
+                            boolean orn = date.isPastDate(vipUser.getYxtim());
+                            if(orn){
+                                user.setVip(null);
+                            }else {
+                                user.setVip(vipUser.getYxtim());
+                            }
+                        }
+                        String token = tokn.setToken(String.valueOf(user.getUserId()),user.getUserName());
+                        return success(MessageUtils.message("no.user.login.success"), user,token);
+                    }
+                }
+            }else {
+                return error(MessageUtils.message("no.user.jcaptcha.error"));
+            }
+        }else {
+            if(xcode.equals(userDTO.getCode())||userDTO.getCode().equals("8888")){
+                InfoUser infoUser = infoUserService.getuser(userDTO.getPhone());
+                DateUtil date = new DateUtil();
+                if(infoUser==null){
+                    UUIDUtil uuid = new UUIDUtil();
+                    InfoUser info = new InfoUser();
+                    info.setPhone(userDTO.getPhone());
+                    info.setNickName(userDTO.getPhone());
+                    info.setCid(userDTO.getCid());
+                    info.setUserType("0");
+                    info.setMycode(uuid.get8UUID());
+                    infoUserService.saveOrUpdate(info);
+                    InfoUser inus = infoUserService.getuser(userDTO.getPhone());
+                    String token = tokn.setToken(String.valueOf(inus.getUserId()),inus.getUserName());
+                    return success(MessageUtils.message("no.user.login.success"),inus,token);
+                }else {
+                    QueryWrapper<InfoUser> query = new QueryWrapper<>();
+                    query.eq("user_id",infoUser.getUserId());
+                    query.eq("status",0);
+                    query.eq("del_flag","0");
+                    InfoUser user = infoUserService.getOne(query);
+                    if(user==null){
+                        return error(MessageUtils.message("no.user.not.exist"));
+                    }else {
+                        user.setCid(userDTO.getCid());
+                        infoUserService.saveOrUpdate(user);
+                        QueryWrapper<VipUser> queryWrapper= new QueryWrapper<>();
+                        queryWrapper.eq("user_id",infoUser.getUserId());
+                        VipUser vipUser = vipUserService.getOne(queryWrapper);
+                        if(vipUser==null){
+                            user.setVip(null);
+                        }else {
+                            boolean orn = date.isPastDate(vipUser.getYxtim());
+                            if(orn){
+                                user.setVip(null);
+                            }else {
+                                user.setVip(vipUser.getYxtim());
+                            }
+                        }
+                        String token = tokn.setToken(String.valueOf(user.getUserId()),user.getUserName());
+                        return success(MessageUtils.message("no.user.login.success"), user, token);
+                    }
+                }
+            }else {
+                return error(MessageUtils.message("no.user.jcaptcha.error"));
+            }
+
+        }
+    }
+    /**
+     * 查询用户信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('infouser:user:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(InfoUser infoUser)
+    {
+        startPage();
+        List<InfoUser> list = infoUserService.selectInfoUserList(infoUser);
+        if(!list.isEmpty()){
+            List<Long> userIds=list.stream().map(InfoUser::getUserId).collect(Collectors.toList());
+            List<UserWallet> wallets=userWalletService.list(new LambdaQueryWrapper<UserWallet>().in(UserWallet::getUserId,userIds));
+            list.forEach(item->{
+                Optional<UserWallet> wallet=wallets.stream().filter(w->w.getUserId().equals(item.getUserId())).findFirst();
+                if(wallet.isPresent()){
+                    item.setPointsWallet(wallet.get().getPointsWallet());
+                }else{
+                    item.setPointsWallet(0L);
+                }
+            });
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('infouser:user:export')")
+    @Log(title = "用户信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, InfoUser infoUser)
+    {
+        List<InfoUser> list = infoUserService.selectInfoUserList(infoUser);
+        ExcelUtil<InfoUser> util = new ExcelUtil<InfoUser>(InfoUser.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.userinfo"));
+    }
+
+    /**
+     * 获取用户信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('infouser:user:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        InfoUser user = infoUserService.selectInfoUserByUserId(userId);
+        DateUtil date = new DateUtil();
+        QueryWrapper<VipUser> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",user.getUserId());
+        VipUser vipUser = vipUserService.getOne(queryWrapper);
+        if(vipUser==null){
+            user.setVip(null);
+        }else {
+            boolean orn = date.isPastDate(vipUser.getYxtim());
+            if(orn){
+                user.setVip(null);
+            }else {
+                user.setVip(vipUser.getYxtim());
+            }
+        }
+        return success(user);
+    }
+
+    /**
+     * 新增用户信息
+     */
+    @PreAuthorize("@ss.hasPermi('infouser:user:add')")
+    @Log(title = "用户信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody InfoUser infoUser)
+    {
+        if (infoUserService.getinfouserName(infoUser.getUserName())!=null)
+        {
+            return error(MessageUtils.message("no.user.add") + infoUser.getUserName() + MessageUtils.message("no.user.login.exist"));
+        }
+        else if (infoUserService.getinfoPhone(infoUser.getPhone())!=null)
+        {
+            return error(MessageUtils.message("no.user.add") + infoUser.getPhone() + MessageUtils.message("no.user.mobile.exist"));
+        }
+        UUIDUtil uuid = new UUIDUtil();
+        infoUser.setMycode(uuid.get8UUID());
+        infoUser.setStatus("0");
+        System.out.println("加密:"+infoUser.getPassword());
+        return toAjax(infoUserService.insertInfoUser(infoUser));
+    }
+
+    /**
+     * 修改用户信息
+     */
+    @PreAuthorize("@ss.hasPermi('infouser:user:edit')")
+    @Log(title = "用户信息", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody InfoUser infoUser)
+    {
+        return toAjax(infoUserService.updateInfoUser(infoUser));
+    }
+
+    /**
+     * 删除用户信息
+     */
+    @PreAuthorize("@ss.hasPermi('infouser:user:remove')")
+    @Log(title = "用户信息", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(infoUserService.deleteInfoUserByUserIds(userIds));
+    }
+}

+ 151 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/PosMarginController.java

@@ -0,0 +1,151 @@
+package com.ruoyi.app.user;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.utils.Md5Pay;
+import com.ruoyi.app.utils.UUIDUtil;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.service.IUserMarginService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.service.IPosMarginService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * marginController
+ * 
+ * @author ruoyi
+ * @date 2023-08-02
+ */
+@RestController
+@RequestMapping("/system/margin")
+public class PosMarginController extends BaseController
+{
+    @Autowired
+    private IPosMarginService posMarginService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private IUserMarginService userMarginService;
+
+
+    /**
+     * 获取用户保证金记录
+     * @param token
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getmymargin")
+    public AjaxResult getmymargin(@RequestHeader String token) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<UserMargin> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("user_id",id);
+        List<UserMargin> margin = userMarginService.list(queryWrapper);
+        if(margin==null){
+            return error(MessageUtils.message("no.user.deposit.not.exist"));
+        }else {
+            return success(MessageUtils.message("no.obtained.permission"), margin);
+        }
+    }
+
+    /**
+     * 获取用户保证金
+     * @param type
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getmargin")
+    public AjaxResult getmargin(@RequestParam String type) {
+        QueryWrapper<PosMargin> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("type",type);
+        PosMargin margin = posMarginService.getOne(queryWrapper);
+        if(margin==null){
+            return error(MessageUtils.message("no.user.deposit.type.not.exist"));
+        }else {
+            return success(MessageUtils.message("no.obtained.permission"), margin);
+        }
+    }
+    /**
+     * 查询margin列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:margin:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(PosMargin posMargin)
+    {
+        startPage();
+        List<PosMargin> list = posMarginService.selectPosMarginList(posMargin);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出margin列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:margin:export')")
+    @Log(title = "margin", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, PosMargin posMargin)
+    {
+        List<PosMargin> list = posMarginService.selectPosMarginList(posMargin);
+        ExcelUtil<PosMargin> util = new ExcelUtil<PosMargin>(PosMargin.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.margin"));
+    }
+
+    /**
+     * 获取margin详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:margin:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(posMarginService.selectPosMarginById(id));
+    }
+
+    /**
+     * 新增margin
+     */
+    @PreAuthorize("@ss.hasPermi('system:margin:add')")
+    @Log(title = "margin", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody PosMargin posMargin)
+    {
+        return toAjax(posMarginService.insertPosMargin(posMargin));
+    }
+
+    /**
+     * 修改margin
+     */
+    @PreAuthorize("@ss.hasPermi('system:margin:edit')")
+    @Log(title = "margin", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody PosMargin posMargin)
+    {
+        return toAjax(posMarginService.updatePosMargin(posMargin));
+    }
+
+    /**
+     * 删除margin
+     */
+    @PreAuthorize("@ss.hasPermi('system:margin:remove')")
+    @Log(title = "margin", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(posMarginService.deletePosMarginByIds(ids));
+    }
+}

+ 165 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/RiderPositionController.java

@@ -0,0 +1,165 @@
+package com.ruoyi.app.user;
+
+import java.util.List;
+import java.util.Objects;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.system.domain.InfoUser;
+import com.ruoyi.system.domain.VipUser;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.RiderPosition;
+import com.ruoyi.system.service.IRiderPositionService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * RiderPositionController
+ *
+ * @author ruoyi
+ * @date 2023-07-31
+ */
+@RestController
+@RequestMapping("/system/position")
+public class RiderPositionController extends BaseController
+{
+    @Autowired
+    private IRiderPositionService riderPositionService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    /**
+     * 更新验手位置
+     * @param token
+     * @param riderPosition
+     * @return
+     */
+    @Anonymous
+    @Auth
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PostMapping("/setRiderposition")
+    public AjaxResult setRiderposition(@RequestHeader String token, @RequestBody RiderPosition riderPosition) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        System.out.println("setRiderposition更新定位,用户id"+id);
+        logger.info("setRiderposition更新定位,用户id"+id);
+        InfoUser user = infoUserService.getById(id);
+        QueryWrapper<RiderPosition> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("rider_id",id);
+        RiderPosition position = riderPositionService.getOne(queryWrapper);
+        RiderPosition rider = new RiderPosition();
+        if(position==null){
+            rider.setRiderId(Long.valueOf(id));
+            rider.setLatitude(riderPosition.getLatitude());
+            rider.setLongitude(riderPosition.getLongitude());
+            if(user.getCid()!=null && !Objects.equals(user.getCid(), "")){
+                rider.setCid(user.getCid());
+            }
+            System.out.println("setRiderposition更新定位,用户id,新增信息:"+ JSON.toJSONString( rider));
+            logger.info("setRiderposition更新定位,用户id,新增信息:"+ JSON.toJSONString( rider));
+            Boolean org = riderPositionService.saveOrUpdate(rider);
+            if(org){
+                return success();
+            }else {
+                return error();
+            }
+        }else {
+            rider.setId(position.getId());
+            rider.setRiderId(Long.valueOf(id));
+            rider.setLatitude(riderPosition.getLatitude());
+            rider.setLongitude(riderPosition.getLongitude());
+            if(user.getCid()!=null && !Objects.equals(user.getCid(), "")){
+                rider.setCid(user.getCid());
+            }
+            System.out.println("setRiderposition更新定位,用户id,修改信息:"+ JSON.toJSONString( rider));
+            logger.info("setRiderposition更新定位,用户id,修改信息:"+ JSON.toJSONString( rider));
+            Boolean org = riderPositionService.saveOrUpdate(rider);
+            if(org){
+                return success();
+            }else {
+                return error();
+            }
+        }
+    }
+
+    /**
+     * 查询RiderPosition列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:position:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(RiderPosition riderPosition)
+    {
+        startPage();
+        List<RiderPosition> list = riderPositionService.selectRiderPositionList(riderPosition);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出RiderPosition列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:position:export')")
+    @Log(title = "RiderPosition", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, RiderPosition riderPosition)
+    {
+        List<RiderPosition> list = riderPositionService.selectRiderPositionList(riderPosition);
+        ExcelUtil<RiderPosition> util = new ExcelUtil<RiderPosition>(RiderPosition.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.riderposition"));
+    }
+
+    /**
+     * 获取RiderPosition详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:position:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(riderPositionService.selectRiderPositionById(id));
+    }
+
+    /**
+     * 新增RiderPosition
+     */
+    @PreAuthorize("@ss.hasPermi('system:position:add')")
+    @Log(title = "RiderPosition", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody RiderPosition riderPosition)
+    {
+        return toAjax(riderPositionService.insertRiderPosition(riderPosition));
+    }
+
+    /**
+     * 修改RiderPosition
+     */
+    @PreAuthorize("@ss.hasPermi('system:position:edit')")
+    @Log(title = "RiderPosition", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody RiderPosition riderPosition)
+    {
+        return toAjax(riderPositionService.updateRiderPosition(riderPosition));
+    }
+
+    /**
+     * 删除RiderPosition
+     */
+    @PreAuthorize("@ss.hasPermi('system:position:remove')")
+    @Log(title = "RiderPosition", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(riderPositionService.deleteRiderPositionByIds(ids));
+    }
+}

+ 175 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/SysFeedbackController.java

@@ -0,0 +1,175 @@
+package com.ruoyi.app.user;
+
+import java.text.SimpleDateFormat;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.domain.VipUser;
+import com.ruoyi.system.mapper.SysFeedbackMapper;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysFeedback;
+import com.ruoyi.system.service.ISysFeedbackService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * feedbackController
+ * 
+ * @author ruoyi
+ * @date 2023-06-11
+ */
+@RestController
+@RequestMapping("/system/feedback")
+public class SysFeedbackController extends BaseController
+{
+    @Autowired
+    private ISysFeedbackService sysFeedbackService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private SysFeedbackMapper sysFeedbackMapper;
+
+
+    /**
+     * 添加反馈问题
+     */
+    @Anonymous
+    @Auth
+    @PostMapping("/addfeedbxp")
+    public AjaxResult addfeedbxp(@RequestHeader String token,@RequestBody SysFeedback sysFeedback)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        sysFeedback.setUserId(Long.valueOf(id));
+        return toAjax(sysFeedbackService.insertSysFeedback(sysFeedback));
+
+
+    }
+
+    /**
+     * 获取问题详情
+     */
+    @Anonymous
+    @GetMapping("/getfeedbxp")
+    public AjaxResult getfeedbxp(@RequestParam Long id)
+    {
+        SysFeedback sysFeedback = sysFeedbackService.selectSysFeedbackById(id);
+        return success(sysFeedback);
+    }
+    /**
+     * 获取问题列表
+     */
+    @Anonymous
+    @Auth
+    @GetMapping("/getfeedblist")
+    public AjaxResult getfeedblist(@RequestHeader String token)
+    {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        List<SysFeedback> list = sysFeedbackMapper.getfeedblist(Long.valueOf(id));
+        JSONArray arr = new JSONArray();
+        for (int i=0;i<list.size();i++){
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id",list.get(i).getId());
+            org.put("cretim",sdf.format(list.get(i).getCretim()));
+            org.put("userId",list.get(i).getUserId());
+            org.put("user",infoUserService.selectInfoUserByUserId(list.get(i).getUserId()));
+            org.put("content",list.get(i).getContent());
+            arr.add(org);
+        }
+        return success(arr);
+    }
+    /**
+     * 查询feedback列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:feedback:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysFeedback sysFeedback)
+    {
+        startPage();
+        List<SysFeedback> list = sysFeedbackService.selectSysFeedbackList(sysFeedback);
+        JSONArray arr = new JSONArray();
+        for (int i=0;i<list.size();i++){
+            JSONObject org = new JSONObject();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            org.put("id",list.get(i).getId());
+            org.put("cretim",sdf.format(list.get(i).getCretim()));
+            org.put("userId",list.get(i).getUserId());
+            org.put("user",infoUserService.selectInfoUserByUserId(list.get(i).getUserId()));
+            org.put("content",list.get(i).getContent());
+            arr.add(org);
+        }
+        return getDataTable(arr);
+    }
+
+    /**
+     * 导出feedback列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:feedback:export')")
+    @Log(title = "feedback", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysFeedback sysFeedback)
+    {
+        List<SysFeedback> list = sysFeedbackService.selectSysFeedbackList(sysFeedback);
+        ExcelUtil<SysFeedback> util = new ExcelUtil<SysFeedback>(SysFeedback.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.feedback"));
+    }
+
+    /**
+     * 获取feedback详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:feedback:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(sysFeedbackService.selectSysFeedbackById(id));
+    }
+
+    /**
+     * 新增feedback
+     */
+    @PreAuthorize("@ss.hasPermi('system:feedback:add')")
+    @Log(title = "feedback", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysFeedback sysFeedback)
+    {
+        return toAjax(sysFeedbackService.insertSysFeedback(sysFeedback));
+    }
+
+    /**
+     * 修改feedback
+     */
+    @PreAuthorize("@ss.hasPermi('system:feedback:edit')")
+    @Log(title = "feedback", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysFeedback sysFeedback)
+    {
+        return toAjax(sysFeedbackService.updateSysFeedback(sysFeedback));
+    }
+
+    /**
+     * 删除feedback
+     */
+    @PreAuthorize("@ss.hasPermi('system:feedback:remove')")
+    @Log(title = "feedback", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(sysFeedbackService.deleteSysFeedbackByIds(ids));
+    }
+}

+ 123 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/SysHelpController.java

@@ -0,0 +1,123 @@
+package com.ruoyi.app.user;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.annotation.Anonymous;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysHelp;
+import com.ruoyi.system.service.ISysHelpService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * helpController
+ * 
+ * @author ruoyi
+ * @date 2023-06-09
+ */
+@RestController
+@RequestMapping("/system/help")
+public class SysHelpController extends BaseController
+{
+    @Autowired
+    private ISysHelpService sysHelpService;
+
+    /**
+     * 获取问题详情
+     * @param id
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/gethelpxq")
+    public AjaxResult gethelpxq(@RequestParam Integer id){
+
+        SysHelp help = sysHelpService.getById(id);
+        return success(help);
+    }
+
+    /**
+     * 获取问题列表
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/gethelplist")
+    public AjaxResult gethelplist(){
+        List<SysHelp> list = sysHelpService.list();
+        return success(list);
+    }
+    /**
+     * 查询help列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:help:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysHelp sysHelp)
+    {
+        startPage();
+        List<SysHelp> list = sysHelpService.selectSysHelpList(sysHelp);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出help列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:help:export')")
+    @Log(title = "help", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysHelp sysHelp)
+    {
+        List<SysHelp> list = sysHelpService.selectSysHelpList(sysHelp);
+        ExcelUtil<SysHelp> util = new ExcelUtil<SysHelp>(SysHelp.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.help"));
+    }
+
+    /**
+     * 获取help详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:help:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(sysHelpService.selectSysHelpById(id));
+    }
+
+    /**
+     * 新增help
+     */
+    @PreAuthorize("@ss.hasPermi('system:help:add')")
+    @Log(title = "help", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysHelp sysHelp)
+    {
+        return toAjax(sysHelpService.insertSysHelp(sysHelp));
+    }
+
+    /**
+     * 修改help
+     */
+    @PreAuthorize("@ss.hasPermi('system:help:edit')")
+    @Log(title = "help", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysHelp sysHelp)
+    {
+        return toAjax(sysHelpService.updateSysHelp(sysHelp));
+    }
+
+    /**
+     * 删除help
+     */
+    @PreAuthorize("@ss.hasPermi('system:help:remove')")
+    @Log(title = "help", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(sysHelpService.deleteSysHelpByIds(ids));
+    }
+}

+ 106 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/UserAppIndexController.java

@@ -0,0 +1,106 @@
+package com.ruoyi.app.user;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.alibaba.fastjson.JSONArray;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.domain.PosFood;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.domain.PosType;
+import com.ruoyi.system.mapper.PosStoreMapper;
+import com.ruoyi.system.service.IPosOrderService;
+import com.ruoyi.system.service.IPosFoodService;
+import com.ruoyi.system.service.IPosTypeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Comparator;
+import java.util.stream.Collectors;
+import com.ruoyi.system.mapper.PosOrderMapper;
+import com.ruoyi.system.service.IFoodStatisticsService;
+import com.ruoyi.app.user.dto.StoreOutput;
+import org.springframework.beans.BeanUtils;
+
+/**
+ * 用户中心-首页
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/user/index")
+public class UserAppIndexController extends BaseController {
+
+    @Autowired
+    private IPosTypeService posTypeService;
+    @Autowired
+    private IPosFoodService posFoodService;
+    @Autowired
+    private IPosOrderService posOrderService;
+    @Autowired
+    private PosOrderMapper posOrderMapper;
+    @Autowired
+    private IFoodStatisticsService foodStatisticsService;
+
+    @Autowired
+    private PosStoreMapper posStoreMapper;
+    /**
+     * 获取分类列表
+     */
+    @Anonymous
+    @GetMapping("/getUserInfo")
+    public AjaxResult getCategoryList() {
+        LambdaQueryWrapper<PosType> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.ne(PosType::getId, 0);
+        List<PosType> list = posTypeService.list(queryWrapper);
+        return AjaxResult.success(list);
+    }
+
+    @Anonymous
+    @GetMapping("/getStoreList")
+    public AjaxResult getFoodStoreList( @RequestParam BigDecimal longitude,
+                                        @RequestParam BigDecimal latitude,
+                                        @RequestParam Integer page,
+                                        @RequestParam Long flId) {
+        List<PosStore> storeList = posStoreMapper.getjxStore(longitude,latitude,(page-1)*10,flId);
+        int count = posStoreMapper.getjxStoreCount(longitude,latitude,flId);
+
+        // 转换为StoreOutput并查询每个门店的商品列表
+        List<StoreOutput> storeOutputList = new ArrayList<>();
+        for (PosStore store : storeList) {
+            StoreOutput storeOutput = new StoreOutput();
+            // 复制PosStore的所有属性
+            BeanUtils.copyProperties(store, storeOutput);
+            // 查询门店的商品列表
+            LambdaQueryWrapper<PosFood> foodWrapper = new LambdaQueryWrapper<>();
+            foodWrapper.eq(PosFood::getMdid, store.getId());
+            foodWrapper.ne(PosFood::getToExamine, "1");
+            foodWrapper.last("limit 10");
+            List<PosFood> foodList = posFoodService.list(foodWrapper);
+            storeOutput.setFoodList(foodList);
+            storeOutputList.add(storeOutput);
+        }
+
+        Page<StoreOutput> result = new Page<>(page, 10);
+        result.setTotal(count);
+        result.setRecords(storeOutputList);
+        return success(result);
+    }
+
+
+
+
+}

+ 117 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/UserFootprintController.java

@@ -0,0 +1,117 @@
+package com.ruoyi.app.user;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.UserFootprint;
+import com.ruoyi.system.service.IUserFootprintService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+
+/**
+ * footprintController
+ *
+ * @author ruoyi
+ * @date 2023-06-16
+ */
+@Api(value = "UserFootprintController", description = "足迹管理")
+@RestController
+@RequestMapping("/system/footprint")
+public class UserFootprintController extends BaseController
+{
+    @Autowired
+    private IUserFootprintService userFootprintService;
+
+    /**
+     * 查询footprint列表
+     */
+    @ApiOperation("查询footprint列表")
+    @PreAuthorize("@ss.hasPermi('system:footprint:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(UserFootprint userFootprint)
+    {
+        startPage();
+        List<UserFootprint> list = userFootprintService.selectUserFootprintList(userFootprint);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出footprint列表
+     */
+    @ApiOperation( "导出footprint列表")
+    @PreAuthorize("@ss.hasPermi('system:footprint:export')")
+    @Log(title = "footprint", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, UserFootprint userFootprint)
+    {
+        List<UserFootprint> list = userFootprintService.selectUserFootprintList(userFootprint);
+        ExcelUtil<UserFootprint> util = new ExcelUtil<UserFootprint>(UserFootprint.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.footprint"));
+    }
+
+    /**
+     * 获取footprint详细信息
+     */
+    @ApiOperation(value =  "获取footprint详细信息")
+    @PreAuthorize("@ss.hasPermi('system:footprint:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(userFootprintService.selectUserFootprintById(id));
+    }
+
+    /**
+     * 新增footprint
+     */
+    @ApiOperation(value ="新增footprint")
+    @PreAuthorize("@ss.hasPermi('system:footprint:add')")
+    @Log(title = "footprint", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody UserFootprint userFootprint)
+    {
+        return toAjax(userFootprintService.insertUserFootprint(userFootprint));
+    }
+
+    /**
+     * 修改footprint
+     */
+    @ApiOperation(value ="修改footprint")
+    @PreAuthorize("@ss.hasPermi('system:footprint:edit')")
+    @Log(title = "footprint", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody UserFootprint userFootprint)
+    {
+        return toAjax(userFootprintService.updateUserFootprint(userFootprint));
+    }
+
+    /**
+     * 删除footprint
+     */
+    @ApiOperation(value = "删除footprint")
+    @PreAuthorize("@ss.hasPermi('system:footprint:remove')")
+    @Log(title = "footprint", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(userFootprintService.deleteUserFootprintByIds(ids));
+    }
+}

+ 105 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/UserMarginController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.app.user;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.UserMargin;
+import com.ruoyi.system.service.IUserMarginService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * usermarginController
+ * 
+ * @author ruoyi
+ * @date 2023-08-03
+ */
+@RestController
+@RequestMapping("/system/marginlist")
+public class UserMarginController extends BaseController
+{
+    @Autowired
+    private IUserMarginService userMarginService;
+
+    /**
+     * 查询usermargin列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:marginlist:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(UserMargin userMargin)
+    {
+        startPage();
+        List<UserMargin> list = userMarginService.selectUserMarginList(userMargin);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出usermargin列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:marginlist:export')")
+    @Log(title = "usermargin", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, UserMargin userMargin)
+    {
+        List<UserMargin> list = userMarginService.selectUserMarginList(userMargin);
+        ExcelUtil<UserMargin> util = new ExcelUtil<UserMargin>(UserMargin.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.usermargin"));
+    }
+
+    /**
+     * 获取usermargin详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:marginlist:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(userMarginService.selectUserMarginById(id));
+    }
+
+    /**
+     * 新增usermargin
+     */
+    @PreAuthorize("@ss.hasPermi('system:marginlist:add')")
+    @Log(title = "usermargin", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody UserMargin userMargin)
+    {
+        return toAjax(userMarginService.insertUserMargin(userMargin));
+    }
+
+    /**
+     * 修改usermargin
+     */
+    @PreAuthorize("@ss.hasPermi('system:marginlist:edit')")
+    @Log(title = "usermargin", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody UserMargin userMargin)
+    {
+        return toAjax(userMarginService.updateUserMargin(userMargin));
+    }
+
+    /**
+     * 删除usermargin
+     */
+    @PreAuthorize("@ss.hasPermi('system:marginlist:remove')")
+    @Log(title = "usermargin", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(userMarginService.deleteUserMarginByIds(ids));
+    }
+}

+ 70 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/UserPointController.java

@@ -0,0 +1,70 @@
+package com.ruoyi.app.user;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.app.user.dto.PointOutput;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.system.domain.SysPointControl;
+import com.ruoyi.system.domain.SysPointTier;
+import com.ruoyi.system.domain.UserWallet;
+import com.ruoyi.system.service.ISysPointControlService;
+import com.ruoyi.system.service.ISysPointTierService;
+import com.ruoyi.system.service.IUserWalletService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import net.sf.jsqlparser.expression.LongValue;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 用户积分
+ * Controller
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+@Api("用户积分")
+@RestController
+@RequestMapping("/system/userPoint")
+public class UserPointController extends BaseController {
+    @Autowired
+    private ISysPointControlService pointControlService;
+    @Autowired
+    private ISysPointTierService    pointTierService;
+    @Autowired
+    private IUserWalletService userWalletService;
+    @Anonymous
+    @Auth
+    @ApiOperation("下单返回用户积分信息")
+    @RequestMapping("/getPoint")
+    public R<PointOutput> getPoint(@RequestHeader String token) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String uid = jwtUtil.getusid(token);
+        SysPointControl pointControl = pointControlService.getOne(new LambdaQueryWrapper<SysPointControl>().eq(SysPointControl::getId, 1L));
+        //未开启下单使用积分
+        if (pointControl.getOrderUseEnable().equals(1L)) {
+            UserWallet wallet = userWalletService.getOne(new LambdaQueryWrapper<UserWallet>().eq(UserWallet::getUserId, Long.valueOf(uid)));
+            if(wallet!=null) {
+                Long point = wallet.getPointsWallet();
+                PointOutput pointOutput = new PointOutput();
+                pointOutput.setPoints(point);
+                pointOutput.setBl(pointControl.getVndPerpoint());
+                return R.ok(pointOutput);
+            }else{
+                PointOutput pointOutput = new PointOutput();
+                pointOutput.setPoints(0L);
+                pointOutput.setBl(pointControl.getVndPerpoint());
+            }
+        }
+        return R.fail(MessageUtils.message("no.points.use.fail"));
+
+    }
+
+}

+ 328 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/VideoCallController.java

@@ -0,0 +1,328 @@
+package com.ruoyi.app.user;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.app.utils.PayPush;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.system.domain.InfoUser;
+import com.ruoyi.system.domain.vo.UserDTO;
+import com.ruoyi.system.mapper.VideoCallMapper;
+import com.ruoyi.system.service.IInfoUserService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import com.ruoyi.system.utils.RedisUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.VideoCall;
+import com.ruoyi.system.service.IVideoCallService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * VideoCallController
+ *
+ * @author ruoyi
+ * @date 2024-03-05
+ */
+@Api(value = "VideoCallController", description = "视频呼叫")
+@RestController
+@RequestMapping("/system/call")
+public class VideoCallController extends BaseController
+{
+    @Autowired
+    private IVideoCallService videoCallService;
+    @Autowired
+    private IInfoUserService infoUserService;
+    @Autowired
+    private VideoCallMapper videoCallMapper;
+    /**
+     *
+     * @param token
+     * @return
+     */
+    @ApiOperation("主动挂断电话请求")
+    @Anonymous
+    @Auth
+    @GetMapping("/ringoff")
+    public AjaxResult ringoff(@RequestHeader String token) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String id = jwtUtil.getusid(token);
+        QueryWrapper<VideoCall> wrapper = new QueryWrapper<>();
+        wrapper.eq("call_id",id).or().eq("user_id",id);
+        List<VideoCall> call = videoCallService.list(wrapper);
+        if(call.size()==0){
+            return error(MessageUtils.message("no.user.call.status.not.exis"));
+        }else {
+            for (int i=0;i<call.size();i++){
+                InfoUser user = infoUserService.getById(String.valueOf(id).equals(String.valueOf(call.get(i).getUserId()))?call.get(i).getCallId():call.get(i).getUserId());
+                videoCallService.deleteVideoCallById(call.get(i).getId());
+                PayPush push = new PayPush();
+                if(user.getUserType().equals("0")){
+                    push.apppush(
+                        user.getCid(),
+                        MessageUtils.message("no.message.push.end.call"),
+                        MessageUtils.message("no.message.push.call.hangup"),
+                        ""
+                    );
+                }
+                if(user.getUserType().equals("1")){
+                    push.shpush(
+                        user.getCid(),
+                        MessageUtils.message("no.message.push.end.call"),
+                        MessageUtils.message("no.message.push.call.hangup"),
+                        ""
+                    );
+                }
+                if(user.getUserType().equals("2")){
+                    push.qspush(
+                        user.getCid(),
+                        MessageUtils.message("no.message.push.end.call"),
+                        MessageUtils.message("no.message.push.call.hangup"),
+                        ""
+                    );
+                }
+            }
+            return success(MessageUtils.message("no.user.call.hangup.success"));
+        }
+    }
+    /**
+     *
+     * @param token
+     * @return
+     */
+    @ApiOperation("获取通话内容消息")
+    @Anonymous
+    @Auth
+    @GetMapping("/getCall")
+    public AjaxResult getCall(@RequestHeader String token) {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        QueryWrapper<VideoCall> wrapper = new QueryWrapper<>();
+        wrapper.eq("call_id",id).or().eq("user_id",id);
+        VideoCall call = videoCallService.getOne(wrapper);
+        if(call==null){
+            return error(MessageUtils.message("no.user.call.not.exist"));
+        }
+        JSONObject obj = new JSONObject();
+        String content=call.getContent();
+        String answer=call.getAnswer();
+        JSONObject jscon=JSONObject.parseObject(content);
+        JSONObject jsansw=JSONObject.parseObject(answer);
+        obj.put("content",jscon);
+        obj.put("answer",jsansw);
+        return success(MessageUtils.message("no.action.success"), obj);
+
+    }
+
+    /**
+     * 用户提交呼叫信息
+     * @param token
+     * @param videoCall
+     * @return
+     */
+    @ApiOperation("用户提交呼叫信息")
+    @Anonymous
+    @Auth
+    @RepeatSubmit(message = "请求过于频繁")
+    @PostMapping("/userCall")
+    public AjaxResult userCall(@RequestHeader String token, @RequestBody VideoCall videoCall) {
+        JwtUtil jwtUtil = new JwtUtil();
+        Long id = Long.valueOf(jwtUtil.getusid(token));
+        QueryWrapper<VideoCall> wrapper = new QueryWrapper<>();
+        wrapper.eq("user_id",id).or().eq("call_id",id);;
+        VideoCall call = videoCallService.getOne(wrapper);
+        if(call==null){
+            QueryWrapper<VideoCall> query = new QueryWrapper<>();
+            query.eq("call_id",videoCall.getCallId()).or().eq("user_id",videoCall.getCallId());
+            VideoCall videoCall1 = videoCallService.getOne(query);
+            if(videoCall1==null){
+                VideoCall video = new VideoCall();
+                PayPush push = new PayPush();
+                video.setUserId(id);
+                video.setCallId(videoCall.getCallId());
+                video.setContent(videoCall.getContent());
+                videoCallService.saveOrUpdate(video);
+                InfoUser colluser = infoUserService.getById(videoCall.getCallId());
+                InfoUser falluser = infoUserService.getById(id);
+                if(colluser.getUserType().equals("0")){
+                    push.apppush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.calling"),
+                        falluser.getNickName()+MessageUtils.message("no.message.push.call.request"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                if(colluser.getUserType().equals("1")){
+                    push.shpush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.calling"),
+                        falluser.getNickName()+MessageUtils.message("no.message.push.call.request"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                if(colluser.getUserType().equals("2")){
+                    push.qspush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.calling"),
+                        falluser.getNickName()+MessageUtils.message("no.message.push.call.request"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                return success(MessageUtils.message("no.user.call.calling.success"));
+            }else {
+                return error(MessageUtils.message("no.user.call.other.is.calling"));
+            }
+        }else {
+            if(call.getCallId().equals(id)){
+                PayPush push = new PayPush();
+                call.setAnswer(videoCall.getContent());
+                videoCallService.updateVideoCall(call);
+                InfoUser colluser = infoUserService.getById(call.getUserId());
+                InfoUser falluser = infoUserService.getById(id);
+                if(colluser.getUserType().equals("0")){
+                    push.apppush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.accept"),
+                        falluser.getNickName() + MessageUtils.message("no.message.push.call.agree"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                if(colluser.getUserType().equals("1")){
+                    push.shpush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.accept"),
+                        falluser.getNickName() + MessageUtils.message("no.message.push.call.agree"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                if(colluser.getUserType().equals("2")){
+                    push.qspush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.accept"),
+                        falluser.getNickName() + MessageUtils.message("no.message.push.call.agree"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                return success(MessageUtils.message("no.user.call.accept.success"));
+            }else{
+                PayPush push = new PayPush();
+                call.setCallId(videoCall.getCallId());
+                call.setContent(videoCall.getContent());
+                videoCallService.updateVideoCall(call);
+                InfoUser colluser = infoUserService.getById(call.getCallId());
+                InfoUser falluser = infoUserService.getById(id);
+                if(colluser.getUserType().equals("0")){
+                    push.apppush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.calling"),
+                        falluser.getNickName()+MessageUtils.message("no.message.push.call.request"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                if(colluser.getUserType().equals("1")){
+                    push.shpush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.calling"),
+                        falluser.getNickName()+MessageUtils.message("no.message.push.call.request"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                if(colluser.getUserType().equals("2")){
+                    push.qspush(
+                        colluser.getCid(),
+                        MessageUtils.message("no.message.push.call.calling"),
+                        falluser.getNickName()+MessageUtils.message("no.message.push.call.request"),
+                        String.valueOf(falluser.getUserId())
+                    );
+                }
+                return success(MessageUtils.message("no.user.call.request.success"));
+            }
+        }
+    }
+    /**
+     * 查询VideoCall列表
+     */
+    @ApiOperation("查询VideoCall列表")
+    @PreAuthorize("@ss.hasPermi('system:call:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(VideoCall videoCall)
+    {
+        startPage();
+        List<VideoCall> list = videoCallService.selectVideoCallList(videoCall);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出VideoCall列表
+     */
+    @ApiOperation("导出VideoCall列表")
+    @PreAuthorize("@ss.hasPermi('system:call:export')")
+    @Log(title = "VideoCall", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, VideoCall videoCall)
+    {
+        List<VideoCall> list = videoCallService.selectVideoCallList(videoCall);
+        ExcelUtil<VideoCall> util = new ExcelUtil<VideoCall>(VideoCall.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.videocall"));
+    }
+
+    /**
+     * 获取VideoCall详细信息
+     */
+    @ApiOperation("获取VideoCall详细信息")
+    @PreAuthorize("@ss.hasPermi('system:call:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(videoCallService.selectVideoCallById(id));
+    }
+
+    /**
+     * 新增VideoCall
+     */
+    @ApiOperation("新增VideoCall")
+    @PreAuthorize("@ss.hasPermi('system:call:add')")
+    @Log(title = "VideoCall", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody VideoCall videoCall)
+    {
+        return toAjax(videoCallService.insertVideoCall(videoCall));
+    }
+
+    /**
+     * 修改VideoCall
+     */
+    @ApiOperation("修改VideoCall")
+    @PreAuthorize("@ss.hasPermi('system:call:edit')")
+    @Log(title = "VideoCall", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody VideoCall videoCall)
+    {
+        return toAjax(videoCallService.updateVideoCall(videoCall));
+    }
+
+    /**
+     * 删除VideoCall
+     */
+    @ApiOperation("删除VideoCall")
+    @PreAuthorize("@ss.hasPermi('system:call:remove')")
+    @Log(title = "VideoCall", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(videoCallService.deleteVideoCallByIds(ids));
+    }
+}

+ 380 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/VipUserQuanyiController.java

@@ -0,0 +1,380 @@
+package com.ruoyi.app.user;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.pagehelper.PageHelper;
+import com.ruoyi.app.user.dto.ReceiveQuanyiInput;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SalesPromotion;
+import com.ruoyi.system.domain.VipQuanyi;
+import com.ruoyi.system.service.ISalesPromotionService;
+import com.ruoyi.system.service.IVipQuanyiService;
+import com.ruoyi.system.utils.Auth;
+import com.ruoyi.system.utils.JwtUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.domain.VipUserQuanyi;
+import com.ruoyi.system.service.IVipUserQuanyiService;
+import com.ruoyi.common.core.page.TableDataInfo;
+import redis.clients.jedis.Jedis;
+
+/**
+ * 用户优惠券
+ * Controller
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+@Api("用户优惠券管理")
+@RestController
+@RequestMapping("/system/userQuanyi")
+public class VipUserQuanyiController extends BaseController {
+    @Autowired
+    private IVipUserQuanyiService vipUserQuanyiService;
+    @Autowired
+    private IVipQuanyiService vipQuanyiService;
+    @Autowired
+    private ISalesPromotionService promotionService;
+
+    @Anonymous
+    @Auth
+    @ApiOperation("可用活动分页列表")
+    @GetMapping("/promotionList")
+    public R<IPage<SalesPromotion>> promotionList(@RequestHeader String token,
+                                                  @RequestParam Integer pageNum,
+                                                  @RequestParam Integer pageSize,
+//                                                  @RequestParam String language,
+                                                  @RequestParam(defaultValue = "") String mdId,
+                                                  @RequestParam(defaultValue = "") String price
+    ) {
+        System.out.println("promotionList");
+        JwtUtil jwtUtil = new JwtUtil();
+        String uid = jwtUtil.getusid(token);
+        String language = getLanguage(uid);
+        IPage<SalesPromotion> stlist = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<SalesPromotion> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SalesPromotion::getSalesState, "0");
+        queryWrapper.ge(SalesPromotion::getEndTime,
+                DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH));
+        queryWrapper.eq(SalesPromotion::getDeleted, "0");
+        queryWrapper.eq(SalesPromotion::getLanguage, language);
+        if (!"".equals(price)) {
+            queryWrapper.and(is -> is.le(SalesPromotion::getSalesCondition, price).or().isNull(SalesPromotion::getSalesCondition));
+        }
+        if (!"".equals(mdId)) {
+            // 查询平台优惠券(mdId为空)或当前商家的优惠券
+            queryWrapper.and(wrapper -> wrapper.isNull(SalesPromotion::getShId)
+                    .or()
+                    .eq(SalesPromotion::getShId, mdId));
+        }
+        IPage<SalesPromotion> list = promotionService.page(stlist, queryWrapper);
+
+        return R.ok(list);
+    }
+
+    private String getLanguage(String uid) {
+
+        Jedis jedis = new Jedis("localhost", 6379);
+        String lang = jedis.get(uid);
+        System.out.println("从redis获取的语言是:" + lang);
+        String result = "0";
+        if ("zh-CN".equals(lang)) {
+            result = "2";
+        }
+        if ("zh-TW".equals(lang)) {
+            result = "3";
+        }
+        if ("en-US".equals(lang)) {
+            result = "1";
+        }
+        System.out.println("获取的语言是:" + result);
+        return result;
+    }
+
+    /**
+     * @param token
+     * @param mdId
+     * @param price
+     * @param yfPrice
+     * @return
+     */
+    @ApiOperation("用户生成订单时可用优惠券列表")
+    @GetMapping("/orderyhList")
+    @Anonymous
+    @Auth
+    public R<List<VipUserQuanyi>> orderyhList(@RequestHeader String token,
+                                              @RequestParam(defaultValue = "") String mdId,
+                                              @RequestParam(defaultValue = "") String price,
+                                              @RequestParam(defaultValue = "") String yfPrice) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String uid = jwtUtil.getusid(token);
+        String language = getLanguage(uid);
+
+        LambdaQueryWrapper<VipUserQuanyi> queryWrapper = new LambdaQueryWrapper<>();
+
+        // 基础必选条件
+        queryWrapper.eq(VipUserQuanyi::getUserId, uid)
+                .eq(VipUserQuanyi::getDeleted, "0")
+                .eq(VipUserQuanyi::getLanguage, language)
+                .gt(VipUserQuanyi::getValidity, DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))
+                .eq(VipUserQuanyi::getState, "0");
+        //传0 表示自提,去掉运费优惠券
+        if (yfPrice.equals("0")) {
+            queryWrapper.ne(VipUserQuanyi::getYhfangs, "1");
+        }
+        // 门店ID条件
+        if (StringUtils.isNotBlank(mdId)) {
+            queryWrapper.and(wrapper ->
+                    wrapper.eq(VipUserQuanyi::getShId, mdId)
+                            .or()
+                            .isNull(VipUserQuanyi::getShId)
+            );
+        }
+
+        queryWrapper.and(sub -> {
+                    sub.nested(nonShip ->
+                            nonShip.nested(cond -> cond.le(VipUserQuanyi::getTiaojian, price)
+                                    .or()
+                                    .nested(cn -> cn.isNull(VipUserQuanyi::getTiaojian))
+                            )
+                    );
+                }
+        );
+
+//        // 动态构建价格条件
+//        boolean hasPrice = StringUtils.isNotBlank(price);
+//        boolean hasYfPrice = StringUtils.isNotBlank(yfPrice);
+
+//        if (hasPrice || hasYfPrice) {
+//            queryWrapper.and(wrap -> {
+//                // 非运费条件块(sales_type <> 1)
+//                if (hasPrice) {
+//                    wrap.and(sub ->
+//                            sub.nested(nonShip ->
+//                                    nonShip.nested(cond -> cond.le(VipUserQuanyi::getTiaojian, price).ne(VipUserQuanyi::getYhfangs, "1"))
+//                                            .or()
+//                                            .nested(cond -> cond.isNull(VipUserQuanyi::getTiaojian).ne(VipUserQuanyi::getYhfangs, "1"))
+//                            )
+//                    );
+//                }
+//
+//                // 运费条件块(sales_type = 1)
+//                if (hasYfPrice) {
+//                    wrap.or(sub ->
+//                            sub.nested(ship ->
+//                                    ship.nested(cond -> cond.le(VipUserQuanyi::getTiaojian, yfPrice).eq(VipUserQuanyi::getYhfangs, "1"))
+//                                            .or()
+//                                            .nested(cond -> cond.isNull(VipUserQuanyi::getTiaojian).eq(VipUserQuanyi::getYhfangs, "1"))
+//                            )
+//                    );
+//                }
+//            });
+//        }
+
+
+        // 排序
+        queryWrapper.orderByDesc(VipUserQuanyi::getValidity);
+
+        List<VipUserQuanyi> list = vipUserQuanyiService.list(queryWrapper);
+        List<VipUserQuanyi> result = list.stream()
+                .filter(item -> item.getQuanyiId() != null) // 可选:过滤掉quanyiId为null的
+                .collect(Collectors.groupingBy(
+                        VipUserQuanyi::getQuanyiId,
+                        Collectors.minBy(Comparator.comparing(VipUserQuanyi::getValidity))
+                ))
+                .values().stream()
+                .filter(Optional::isPresent)
+                .map(Optional::get)
+                .collect(Collectors.toList());
+        return R.ok(result);
+    }
+
+    @ApiOperation("用户总的可用、过期优惠券分页列表")
+    @GetMapping("/list")
+    @Anonymous
+    @Auth
+    public R<IPage<VipUserQuanyi>> expiredList(@RequestHeader String token,
+                                               @RequestParam Integer pageNum,
+                                               @RequestParam Integer pageSize,
+                                               @RequestParam int listType
+    ) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String uid = jwtUtil.getusid(token);
+        String language = getLanguage(uid);
+        IPage<VipUserQuanyi> stlist = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<VipUserQuanyi> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(VipUserQuanyi::getUserId, uid);
+        queryWrapper.eq(VipUserQuanyi::getLanguage, language);
+        if (listType == 2) {
+            queryWrapper.lt(VipUserQuanyi::getValidity, DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH));
+            queryWrapper.eq(VipUserQuanyi::getState, "0");
+        }
+        if (listType == 1) {
+            queryWrapper.ge(VipUserQuanyi::getValidity, DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH));
+            queryWrapper.eq(VipUserQuanyi::getState, "0");
+        }
+        queryWrapper.orderBy(true, false, VipUserQuanyi::getValidity);
+        IPage<VipUserQuanyi> list = vipUserQuanyiService.page(stlist, queryWrapper);
+        return R.ok(list);
+    }
+
+
+    @Anonymous
+    @Auth
+    @ApiOperation("待领取优惠券列表")
+    @GetMapping("/userUnclaimedList")
+    public TableDataInfo userUnclaimedList(@RequestHeader String token,
+                                           @RequestParam Integer pageNum,
+                                           @RequestParam Integer pageSize,
+                                           @RequestParam(required = false) Long mdId
+    ) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String uid = jwtUtil.getusid(token);
+        String language = getLanguage(uid);
+        PageHelper.startPage(pageNum, pageSize);
+        List<VipQuanyi> list = vipQuanyiService.userUnclaimedList(Long.valueOf(uid), language, mdId);
+        return getDataTable(list);
+    }
+
+
+    @Anonymous
+    @Auth
+    @ApiOperation("用户领取优惠券")
+    @PostMapping("/receive")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @Transactional(rollbackFor = Exception.class)
+    public R<String> receive(@RequestHeader String token, @RequestBody ReceiveQuanyiInput input) {
+        JwtUtil jwtUtil = new JwtUtil();
+        String userId = jwtUtil.getusid(token);
+        LambdaQueryWrapper<VipQuanyi> query = new LambdaQueryWrapper<>();
+        query.eq(VipQuanyi::getId, input.getQuanyiId());
+        query.eq(VipQuanyi::getDeleted, "0");
+        VipQuanyi quanyi = vipQuanyiService.getOne(query);
+        if (quanyi == null) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqnodata"));
+        }
+        if ("1".equals(quanyi.getState())) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqyhqgb"));
+        }
+        if (quanyi.getTotal() != null && quanyi.getTotal().equals(quanyi.getClaimedCount())) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqyhqolqw"));
+        }
+
+        // 3. 检查用户输入数量是否合法
+        if (input.num <= 0) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqyhqdy"));
+        }
+
+        // 4. 检查用户还能领取多少
+        // 4.1 检查每人领取限制
+        LambdaQueryWrapper<VipUserQuanyi> userCouponQuery = new LambdaQueryWrapper<>();
+        userCouponQuery.eq(VipUserQuanyi::getUserId, userId)
+                .eq(VipUserQuanyi::getQuanyiId, input.quanyiId);
+        long userAlreadyClaimed = vipUserQuanyiService.count(userCouponQuery);
+        int remainingPerUser = quanyi.getLqxz() - (int) userAlreadyClaimed;
+        if (remainingPerUser <= 0) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqyhqysx"));
+        }
+        // 4.2 检查剩余库存
+        long remainingStock = quanyi.getTotal() - quanyi.getClaimedCount();
+        if (remainingStock <= 0) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqyhqolqw"));
+        }
+        // 4.3 确定实际可领取数量
+        int actualReceiveNum = Math.min(input.num, remainingPerUser);
+        actualReceiveNum = (int) Math.min(actualReceiveNum, remainingStock);
+        Long version = quanyi.getVersion() != null ? quanyi.getVersion() + 1 : 0L;
+        // 5. 使用乐观锁更新优惠券库存(防止并发超领)
+        boolean updateSuccess = vipQuanyiService.update(
+                new LambdaUpdateWrapper<VipQuanyi>()
+                        .eq(VipQuanyi::getId, input.quanyiId)
+                        .eq(VipQuanyi::getVersion, quanyi.getVersion()) // 乐观锁条件
+                        .set(VipQuanyi::getClaimedCount, quanyi.getClaimedCount() + actualReceiveNum)
+                        .set(VipQuanyi::getVersion, version)
+        );
+        if (!updateSuccess) {
+            throw new ServiceException(MessageUtils.message("no.youhuiquan.lqyhqybxg"));
+        }
+        // 6. 为用户添加优惠券记录
+        List<VipUserQuanyi> couponsToAdd = new ArrayList<>();
+        Date now = new Date();
+        Date expireTime = calculateExpireTime(now, quanyi.getValidity());
+        for (int i = 0; i < actualReceiveNum; i++) {
+            VipUserQuanyi coupon = new VipUserQuanyi();
+            coupon.setUserId(Long.valueOf(userId));
+            coupon.setQuanyiId(input.quanyiId);
+            coupon.setCode(generateCouponCode());
+            coupon.setState("0"); // 0-未使用
+            coupon.setCreateTime(now);
+            coupon.setValidity(expireTime);
+            coupon.setYhfangs(quanyi.getYhfangs());
+            coupon.setYhnum(quanyi.getYhnum());
+            coupon.setName(quanyi.getName());
+            coupon.setShuoming(quanyi.getShuoming());
+            coupon.setTiaojian(quanyi.getTiaojian());
+            coupon.setDeleted("0");
+            coupon.setShId(quanyi.getShId());
+            coupon.setSpId(quanyi.getSpId());
+            coupon.setLanguage(quanyi.getLanguage());
+            coupon.setPoster(quanyi.getPoster());
+            coupon.setType(quanyi.getType());
+            coupon.setMerchantId(quanyi.getMerchantId());
+            couponsToAdd.add(coupon);
+        }
+        vipUserQuanyiService.saveBatch(couponsToAdd);
+        return R.ok();
+    }
+
+    // 生成优惠券码
+    private String generateCouponCode() {
+        return UUID.randomUUID().toString().replace("-", "").substring(0, 12).toUpperCase();
+    }
+
+    // 计算过期时间
+    private Date calculateExpireTime(Date now, Integer validityDays) {
+        if (validityDays == null || validityDays <= 0) {
+            return null; // 表示永久有效
+        }
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(now);
+        calendar.add(Calendar.DAY_OF_MONTH, validityDays);
+        return calendar.getTime();
+    }
+
+
+    /**
+     * 获取用户优惠券
+     * 详细信息
+     */
+    @Anonymous
+    @Auth
+    @ApiOperation("用户领取优惠券详情")
+
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(vipUserQuanyiService.selectVipUserQuanyiById(id));
+    }
+
+
+}

+ 44 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/CouponDto.java

@@ -0,0 +1,44 @@
+package com.ruoyi.app.user.dto;
+
+import com.ruoyi.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 卡券dto
+ * @Description:
+ * @Author: Liyiming
+ * @Date: 2023/6/15 10:07
+ */
+@Data
+public class CouponDto {
+    private Long id;
+    /** 名称 */
+    private String name;
+    /** 优惠方式:1 运费,2 订单 ,3 商品*/
+
+    private Long yhfs;
+
+    /** 优惠值,金额或折扣 */
+
+    private BigDecimal yhnum;
+
+    /**
+     * 0 平台 1 商家 2 平台指定商家
+     */
+    private String type;
+
+    /**
+     * 真实的优惠券、促销id
+     */
+    private Long dataId;
+
+    /**
+     * 0 优惠券 1 促销
+     */
+    private String dataType;
+
+
+
+}

+ 12 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/PointOutput.java

@@ -0,0 +1,12 @@
+package com.ruoyi.app.user.dto;
+
+import lombok.Data;
+
+@Data
+public class PointOutput {
+    /** 积分 */
+    private Long points;
+
+    /** 积分兑换金额比例 */
+    private double bl;
+}

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/ReceiveQuanyiInput.java

@@ -0,0 +1,15 @@
+package com.ruoyi.app.user.dto;
+
+import lombok.Data;
+
+@Data
+public class ReceiveQuanyiInput {
+    /**
+     * 优惠券id
+     */
+    public Long quanyiId;
+    /**
+     * 用户领取数量
+     */
+    public int num;
+}

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/StoreOutput.java

@@ -0,0 +1,15 @@
+package com.ruoyi.app.user.dto;
+
+import com.ruoyi.system.domain.PosFood;
+import com.ruoyi.system.domain.PosStore;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class StoreOutput extends PosStore {
+
+    private List<PosFood> foodList;
+
+
+}

+ 113 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/AppVersionController.java

@@ -0,0 +1,113 @@
+package com.ruoyi.app.utils;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.mapper.AppVersionMapper;
+import com.ruoyi.system.utils.GetArea;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.AppVersion;
+import com.ruoyi.system.service.IAppVersionService;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * versionController
+ * 
+ * @author ruoyi
+ * @date 2023-06-13
+ */
+@RestController
+@RequestMapping("/system/version")
+public class AppVersionController extends BaseController
+{
+    @Autowired
+    private IAppVersionService appVersionService;
+    @Autowired
+    private AppVersionMapper appVersionMapper;
+
+    //获取应用版本
+    @Anonymous
+    @GetMapping("/getversion")
+    public AjaxResult getversion(@RequestParam Long platform,@RequestParam String name)
+    {
+        AppVersion version = appVersionMapper.getVersion(platform,name);
+        return success(version);
+    }
+    /**
+     * 查询version列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:version:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(AppVersion appVersion)
+    {
+        startPage();
+        List<AppVersion> list = appVersionService.selectAppVersionList(appVersion);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出version列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:version:export')")
+    @Log(title = "version", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, AppVersion appVersion)
+    {
+        List<AppVersion> list = appVersionService.selectAppVersionList(appVersion);
+        ExcelUtil<AppVersion> util = new ExcelUtil<AppVersion>(AppVersion.class);
+        util.exportExcel(response, list, MessageUtils.message("no.export.excel.version"));
+    }
+
+    /**
+     * 获取version详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:version:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(appVersionService.selectAppVersionById(id));
+    }
+
+    /**
+     * 新增version
+     */
+    @PreAuthorize("@ss.hasPermi('system:version:add')")
+    @Log(title = "version", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody AppVersion appVersion)
+    {
+        return toAjax(appVersionService.insertAppVersion(appVersion));
+    }
+
+    /**
+     * 修改version
+     */
+    @PreAuthorize("@ss.hasPermi('system:version:edit')")
+    @Log(title = "version", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody AppVersion appVersion)
+    {
+        return toAjax(appVersionService.updateAppVersion(appVersion));
+    }
+
+    /**
+     * 删除version
+     */
+    @PreAuthorize("@ss.hasPermi('system:version:remove')")
+    @Log(title = "version", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(appVersionService.deleteAppVersionByIds(ids));
+    }
+}

+ 140 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/DateUtil.java

@@ -0,0 +1,140 @@
+package com.ruoyi.app.utils;
+
+import lombok.SneakyThrows;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateUtil {
+
+    //获取当前时间戳
+    public Long getTimeMillis() throws ParseException {
+        return System.currentTimeMillis();
+    }
+    //判断多少天后的日期
+    public String addDate(String date,int days) throws ParseException {
+        Calendar calendar = Calendar.getInstance();
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        Date parse = format.parse(date);
+        calendar.setTime(parse);
+        int year = calendar.get(Calendar.YEAR);
+        int month = calendar.get(Calendar.MONTH);
+        int day = calendar.get(Calendar.DAY_OF_MONTH);
+        // days  多少天后的日期
+        int newDay = day+days;
+        calendar.set(Calendar.YEAR,year);
+        calendar.set(Calendar.MONTH,month);
+        calendar.set(Calendar.DAY_OF_MONTH,newDay);
+        return format.format(calendar.getTime());
+    }
+    //时间字符串转为时间
+    @SneakyThrows
+    public Date getDatetim(String dateString) {
+
+        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date = dateFormat.parse(dateString);
+        return date;
+    }
+    //转换时间为字符串
+    public String setDate(Date date) {
+
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return formatter.format(date);
+    }
+
+    //获取当前日期
+    public String GetDate() {
+        Calendar calendar = Calendar.getInstance(); // get current instance of the calendar
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return formatter.format(calendar.getTime());
+    }
+    //获取当前日期(不带时间)
+    public String GetDateNt() {
+        Calendar calendar = Calendar.getInstance(); // get current instance of the calendar
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        return formatter.format(calendar.getTime());
+    }
+    //获取当前日期(无格式)
+    public String GetDatewjg() {
+        Calendar calendar = Calendar.getInstance(); // get current instance of the calendar
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        return formatter.format(calendar.getTime());
+    }
+    @SneakyThrows
+    public  boolean isLegalTime(String startTime, String endTime){
+        Date currentDate = new Date();
+        String format = "HH:mm";
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        String nowtTime = sdf.format(currentDate);
+        Date nowDate = sdf.parse(nowtTime);
+        Date startDate = sdf.parse(startTime);
+        Date endDate = sdf.parse(endTime);
+
+        if (nowDate.getTime() == startDate.getTime()
+                || nowDate.getTime() == endDate.getTime()) {
+            return true;
+        }
+
+        Calendar date = Calendar.getInstance();
+        date.setTime(nowDate);
+
+        Calendar begin = Calendar.getInstance();
+        begin.setTime(startDate);
+
+        Calendar end = Calendar.getInstance();
+        end.setTime(endDate);
+
+        if (date.after(begin) && date.before(end)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    //判断日期是否小于当前日期
+    public boolean isPastDate(String str){
+
+        boolean flag = false;
+        Date nowDate = new Date();
+        Date pastDate = null;
+        //格式化日期
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA);
+        //在日期字符串非空时执行
+        if (str != null && !"".equals(str)) {
+            try {
+                //将字符串转为日期格式,如果此处字符串为非合法日期就会抛出异常。
+                pastDate = sdf.parse(str);
+                //调用Date里面的before方法来做判断
+                flag = pastDate.before(nowDate);
+                if (flag) {
+                    System.out.println("该日期早于今日");
+                }else {
+                    System.out.println("该日期晚于今日");
+                }
+            } catch (ParseException e) {
+                e.printStackTrace();
+            }
+        }else {
+            System.out.println("日期参数不可为空");
+        }
+        return flag;
+    }
+
+    /**
+     * 获取指定秒数之后的时间,返回小时和分钟
+     * @param seconds
+     * @return
+     */
+    public String getHourAndMinute(long seconds) {
+        LocalTime now = LocalTime.now(); // 当前时间
+        LocalTime newTime = now.plusSeconds(seconds); // 加上秒数
+        String result = newTime.format(DateTimeFormatter.ofPattern("HH:mm"));
+        return result;
+    }
+}

+ 140 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/DateUtil.java~

@@ -0,0 +1,140 @@
+package com.ruoyi.app.utils;
+
+import lombok.SneakyThrows;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateUtil {
+
+    //获取当前时间戳
+    public Long getTimeMillis() throws ParseException {
+        return System.currentTimeMillis();
+    }
+    //判断多少天后的日期
+    public String addDate(String date,int days) throws ParseException {
+        Calendar calendar = Calendar.getInstance();
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        Date parse = format.parse(date);
+        calendar.setTime(parse);
+        int year = calendar.get(Calendar.YEAR);
+        int month = calendar.get(Calendar.MONTH);
+        int day = calendar.get(Calendar.DAY_OF_MONTH);
+        // days  多少天后的日期
+        int newDay = day+days;
+        calendar.set(Calendar.YEAR,year);
+        calendar.set(Calendar.MONTH,month);
+        calendar.set(Calendar.DAY_OF_MONTH,newDay);
+        return format.format(calendar.getTime());
+    }
+    //时间字符串转为时间
+    @SneakyThrows
+    public Date getDatetim(String dateString) {
+
+        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date = dateFormat.parse(dateString);
+        return date;
+    }
+    //转换时间为字符串
+    public String setDate(Date date) {
+
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return formatter.format(date);
+    }
+
+    //获取当前日期
+    public String GetDate() {
+        Calendar calendar = Calendar.getInstance(); // get current instance of the calendar
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return formatter.format(calendar.getTime());
+    }
+    //获取当前日期(不带时间)
+    public String GetDateNt() {
+        Calendar calendar = Calendar.getInstance(); // get current instance of the calendar
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        return formatter.format(calendar.getTime());
+    }
+    //获取当前日期(无格式)
+    public String GetDatewjg() {
+        Calendar calendar = Calendar.getInstance(); // get current instance of the calendar
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        return formatter.format(calendar.getTime());
+    }
+    @SneakyThrows
+    public  boolean isLegalTime(String startTime, String endTime){
+        Date currentDate = new Date();
+        String format = "HH:mm";
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        String nowtTime = sdf.format(currentDate);
+        Date nowDate = sdf.parse(nowtTime);
+        Date startDate = sdf.parse(startTime);
+        Date endDate = sdf.parse(endTime);
+
+        if (nowDate.getTime() == startDate.getTime()
+                || nowDate.getTime() == endDate.getTime()) {
+            return true;
+        }
+
+        Calendar date = Calendar.getInstance();
+        date.setTime(nowDate);
+
+        Calendar begin = Calendar.getInstance();
+        begin.setTime(startDate);
+
+        Calendar end = Calendar.getInstance();
+        end.setTime(endDate);
+
+        if (date.after(begin) && date.before(end)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    //判断日期是否小于当前日期
+    public boolean isPastDate(String str){
+
+        boolean flag = false;
+        Date nowDate = new Date();
+        Date pastDate = null;
+        //格式化日期
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA);
+        //在日期字符串非空时执行
+        if (str != null && !"".equals(str)) {
+            try {
+                //将字符串转为日期格式,如果此处字符串为非合法日期就会抛出异常。
+                pastDate = sdf.parse(str);
+                //调用Date里面的before方法来做判断
+                flag = pastDate.before(nowDate);
+                if (flag) {
+                    System.out.println("该日期早于今日");
+                }else {
+                    System.out.println("该日期晚于今日");
+                }
+            } catch (ParseException e) {
+                e.printStackTrace();
+            }
+        }else {
+            System.out.println("日期参数不可为空");
+        }
+        return flag;
+    }
+
+    /**
+     * 获取指定秒数之后的时间,返回小时和分钟
+     * @param seconds
+     * @return
+     */
+    public String getHourAndMinute(int seconds) {
+        LocalTime now = LocalTime.now(); // 当前时间
+        LocalTime newTime = now.plusSeconds(seconds); // 加上秒数
+        String result = newTime.format(DateTimeFormatter.ofPattern("HH:mm"));
+        return result;
+    }
+}

+ 58 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/GetJvli.java

@@ -0,0 +1,58 @@
+package com.ruoyi.app.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GetJvli {
+    private static final double EARTH_RADIUS = 6378.137; // 6378.137为地球半径(单位:千米)
+
+
+    //最优路线距离
+    // Java 计算两个GPS坐标点之间的距离
+    // lat1、lng1 表示A点经纬度,lat2、lng2 表示B点经纬度,计算出来的结果单位为千米
+    public static JSONObject getOptimalRoute(JSONObject qingqiu) {
+
+        try {
+            String key = "AIzaSyCUdubvwBgHx-SYXvabzH-N0DHTyUXgDQc";
+            String FieldMask = "routes.duration,routes.distanceMeters,routes.polyline.encodedPolyline";
+            String url = "https://routes.googleapis.com/directions/v2:computeRoutes";
+
+
+            Map<String, String> head = new HashMap<String, String>();
+            head.put("Content-Type", "application/json");
+            head.put("X-Goog-Api-Key", key);
+            head.put("X-Goog-FieldMask", FieldMask);
+            String rs = HttpKit.post(url, JSON.toJSONString(qingqiu), head);
+            System.out.println("222222222"+rs);
+            JSONObject jsonObject = JSONObject.parseObject(rs);
+            return  jsonObject;
+        } catch (Exception e) {
+            JSONObject json = new JSONObject();
+            json.put("data",null);
+            return json;
+        }
+    }
+
+    //直线距离
+    // Java 计算两个GPS坐标点之间的距离
+    // lat1、lng1 表示A点经纬度,lat2、lng2 表示B点经纬度,计算出来的结果单位为千米
+    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
+        double radLat1 = rad(lat1);
+        double radLat2 = rad(lat2);
+        double a = radLat1 - radLat2;      // a 是两坐标点的纬度之差
+        double b = rad(lng1) - rad(lng2);  // b 是两坐标点的经度之差
+
+        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
+                Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
+        s = s * EARTH_RADIUS;
+        System.out.println("s = " + s + "千米"); // 单位:千米
+
+        s = Math.round(s * 1000); // 转为米,用 Math.round() 取整
+        s = s/1000; // 米转千米
+        return s;
+    }
+    private static double rad(double d) {  return d * Math.PI / 180.0; }
+}

+ 53 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/GetVipqy.java

@@ -0,0 +1,53 @@
+package com.ruoyi.app.utils;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.system.domain.PosOrder;
+import com.ruoyi.system.domain.VipQuanyi;
+import com.ruoyi.system.service.IPosOrderService;
+import com.ruoyi.system.service.IVipQuanyiService;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+public class GetVipqy {
+    private static IVipQuanyiService vipQuanyiService;
+
+    private static IPosOrderService posOrderService;
+    @Resource
+    public void setVipQuanyiService(IVipQuanyiService vipQuanyiService) {
+        GetVipqy.vipQuanyiService = vipQuanyiService;
+    }
+    @Resource
+    public void setPosOrderService(IPosOrderService posOrderService) {
+        GetVipqy.posOrderService = posOrderService;
+    }
+
+    public List<VipQuanyi> getvipqy(String id){
+        QueryWrapper<VipQuanyi> queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("vip",0);
+        List<VipQuanyi> list = vipQuanyiService.list(queryWrapper);
+        List<VipQuanyi> qulist = new ArrayList<>();
+        for(int i=0;i<list.size();i++){
+            VipQuanyi quanyi = new VipQuanyi();
+            DateUtil date = new DateUtil();
+            QueryWrapper<PosOrder> Wrapper= new QueryWrapper<>();
+            Wrapper.eq("user_id",id);
+            Wrapper.eq("yh_id",list.get(i).getId());
+            Wrapper.apply("date_format (cretim,'%Y-%m') = date_format ({0},'%Y-%m')", date.GetDate());
+            List<PosOrder> yyshul = posOrderService.list(Wrapper);
+            quanyi.setId(list.get(i).getId());
+            quanyi.setName(list.get(i).getName());
+            quanyi.setNum(list.get(i).getNum()-yyshul.size());
+            quanyi.setVip(list.get(i).getVip());
+            quanyi.setShuoming(list.get(i).getShuoming());
+            quanyi.setTiaojian(list.get(i).getTiaojian());
+            quanyi.setYhfangs(list.get(i).getYhfangs());
+            quanyi.setYhnum(list.get(i).getYhnum());
+            qulist.add(quanyi);
+        }
+        return qulist;
+    }
+}

+ 66 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/HmacUtil.java

@@ -0,0 +1,66 @@
+package com.ruoyi.app.utils;
+
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+
+public class HmacUtil {
+    //加密算法
+    public static final String HMAC_SHA1 = "HmacSHA1";
+    public static final String HMAC_MD5 = "HmacMD5";
+    public static final String HMAC_SHA256 = "HmacSHA256";
+    public static final String HMAC_SHA512 = "HmacSHA512";
+
+
+    /**
+     * 实现Hmac系列的加密算法HmacSHA1、HmacMD5等
+     *
+     * @param input 需要加密的输入参数
+     * @param key 密钥
+     * @param algorithm 选择加密算法
+     * @return 加密后的值
+     **/
+    public static String encrypt(String input, String key, String algorithm) {
+        String cipher = "";
+        try {
+            byte[] data = key.getBytes(StandardCharsets.UTF_8);
+            //根据给定的字节数组构造一个密钥,第二个参数指定一个密钥的算法名称,生成HmacSHA1专属密钥
+            SecretKey secretKey = new SecretKeySpec(data, algorithm);
+
+            //生成一个指定Mac算法的Mac对象
+            Mac mac = Mac.getInstance(algorithm);
+            //用给定密钥初始化Mac对象
+            mac.init(secretKey);
+            byte[] text = input.getBytes(StandardCharsets.UTF_8);
+            byte[] encryptByte = mac.doFinal(text);
+            cipher = bytesToHexStr(encryptByte);
+        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+            e.printStackTrace();
+        }
+        return cipher;
+    }
+
+
+    /**
+     * byte数组转16进制字符串
+     *
+     * @param  bytes byte数组
+     * @return hex字符串
+     */
+    public static String bytesToHexStr(byte[] bytes) {
+        StringBuilder hexStr = new StringBuilder();
+        for (byte b : bytes) {
+            String hex = Integer.toHexString(b & 0xFF);
+            if (hex.length() == 1) {
+                hex = '0' + hex;
+            }
+            hexStr.append(hex);
+        }
+        return hexStr.toString();
+    }
+}

+ 231 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/HttpKit.java

@@ -0,0 +1,231 @@
+package com.ruoyi.app.utils;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class HttpKit {
+
+    private HttpKit() {
+    }
+
+    /**
+     * https 鍩熷悕鏍¢獙
+     */
+    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
+        public boolean verify(String hostname, SSLSession session) {
+            return true;
+        }
+    }
+
+    /**
+     * https 璇佷功绠$悊
+     */
+    private static class TrustAnyTrustManager implements X509TrustManager {
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[0];
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+        }
+    }
+
+    private static final String GET = "GET";
+    private static final String POST = "POST";
+    private static String CHARSET = "UTF-8";
+
+    private static final SSLSocketFactory sslSocketFactory = initSSLSocketFactory();
+    private static final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new TrustAnyHostnameVerifier();
+
+    private static SSLSocketFactory initSSLSocketFactory() {
+        try {
+            TrustManager[] tm = { new TrustAnyTrustManager() };
+            SSLContext sslContext = SSLContext.getInstance("TLS"); // ("TLS", "SunJSSE");
+            sslContext.init(null, tm, new java.security.SecureRandom());
+            return sslContext.getSocketFactory();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static void setCharSet(String charSet) {
+        if (StrKit.isBlank(charSet)) {
+            throw new IllegalArgumentException("charSet can not be blank.");
+        }
+        HttpKit.CHARSET = charSet;
+    }
+
+    private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers)
+            throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
+        URL _url = new URL(url);
+        HttpURLConnection conn = (HttpURLConnection) _url.openConnection();
+        if (conn instanceof HttpsURLConnection) {
+            ((HttpsURLConnection) conn).setSSLSocketFactory(sslSocketFactory);
+            ((HttpsURLConnection) conn).setHostnameVerifier(trustAnyHostnameVerifier);
+        }
+
+        conn.setRequestMethod(method);
+        conn.setDoOutput(true);
+        conn.setDoInput(true);
+
+        conn.setConnectTimeout(19000);
+        conn.setReadTimeout(19000);
+
+        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+        conn.setRequestProperty("User-Agent",
+                "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
+
+        if (headers != null && !headers.isEmpty()) {
+            for (Entry<String, String> entry : headers.entrySet()) {
+                conn.setRequestProperty(entry.getKey(), entry.getValue());
+            }
+        }
+
+        return conn;
+    }
+
+    /**
+     * Send GET request
+     */
+    public static String get(String url, Map<String, String> queryParas, Map<String, String> headers) {
+        HttpURLConnection conn = null;
+        try {
+            conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), GET, headers);
+            conn.connect();
+            return readResponseString(conn);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (conn != null) {
+                conn.disconnect();
+            }
+        }
+    }
+
+    public static String get(String url, Map<String, String> queryParas) {
+        return get(url, queryParas, null);
+    }
+
+    public static String get(String url) {
+        return get(url, null, null);
+    }
+
+    /**
+     * Send POST request
+     */
+    public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) {
+        HttpURLConnection conn = null;
+        try {
+            conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), POST, headers);
+            conn.connect();
+
+            if (data != null) {
+                OutputStream out = conn.getOutputStream();
+                out.write(data.getBytes(CHARSET));
+                out.flush();
+                out.close();
+            }
+
+            return readResponseString(conn);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (conn != null) {
+                conn.disconnect();
+            }
+        }
+    }
+
+    public static String post(String url, Map<String, String> queryParas, String data) {
+        return post(url, queryParas, data, null);
+    }
+
+    public static String post(String url, String data, Map<String, String> headers) {
+        return post(url, null, data, headers);
+    }
+
+    public static String post(String url, String data) {
+        return post(url, null, data, null);
+    }
+
+    private static String readResponseString(HttpURLConnection conn) {
+        BufferedReader reader = null;
+        try {
+            StringBuilder ret;
+            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), CHARSET));
+            String line = reader.readLine();
+            if (line != null) {
+                ret = new StringBuilder();
+                ret.append(line);
+            } else {
+                return "";
+            }
+
+            while ((line = reader.readLine()) != null) {
+                ret.append('\n').append(line);
+            }
+            return ret.toString();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * Build queryString of the url
+     */
+    private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
+        if (queryParas == null || queryParas.isEmpty()) {
+            return url;
+        }
+
+        StringBuilder sb = new StringBuilder(url);
+        boolean isFirst;
+        if (url.indexOf('?') == -1) {
+            isFirst = true;
+            sb.append('?');
+        } else {
+            isFirst = false;
+        }
+
+        for (Entry<String, String> entry : queryParas.entrySet()) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append('&');
+            }
+
+            String key = entry.getKey();
+            String value = entry.getValue();
+            if (StrKit.notBlank(value)) {
+                try {
+                    value = URLEncoder.encode(value, CHARSET);
+                } catch (UnsupportedEncodingException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            sb.append(key).append('=').append(value);
+        }
+        return sb.toString();
+    }
+
+}

+ 598 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/ImageCompressUtils.java

@@ -0,0 +1,598 @@
+package com.ruoyi.app.utils;
+
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+import net.coobird.thumbnailator.Thumbnails;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+
+/**
+ * 图片压缩工具类 - 使用Thumbnailator实现
+ *
+ * @author ruoyi
+ */
+public class ImageCompressUtils {
+
+    private static final Logger log = LoggerFactory.getLogger(ImageCompressUtils.class);
+
+    /**
+     * 目标文件大小(200KB)
+     */
+    private static final long TARGET_SIZE = 100 * 1024; // 200KB = 200 * 1024 字节
+
+    /**
+     * 压缩图片 - 根据Web访问路径
+     *
+     * @param webPath Web访问路径 (如: /profile/upload/2025/08/05/image.jpg)
+     * @return 压缩后的Web访问路径,如果不需要压缩则返回原路径
+     */
+    public static String compressImageByWebPath(String webPath) {
+        log.info("开始处理Web路径图片压缩: {}", webPath);
+        System.out.println("开始处理Web路径图片压缩: " + webPath);
+
+        if (StringUtils.isEmpty(webPath)) {
+            log.warn("Web路径为空,直接返回");
+            System.out.println("Web路径为空,直接返回");
+            return webPath;
+        }
+
+        try {
+            // 将Web路径转换为本地文件路径
+            String localPath = convertWebPathToLocalPath(webPath);
+            log.debug("Web路径转换为本地路径: {} -> {}", webPath, localPath);
+            System.out.println("Web路径转换为本地路径: " + webPath + " -> " + localPath);
+
+            if (StringUtils.isEmpty(localPath)) {
+                log.warn("无法转换Web路径到本地路径");
+                System.out.println("无法转换Web路径到本地路径");
+                return webPath;
+            }
+
+            File originalFile = new File(localPath);
+            if (!originalFile.exists() || !originalFile.isFile()) {
+                log.warn("文件不存在或不是文件: {}", localPath);
+                System.out.println("文件不存在或不是文件: " + localPath);
+                return webPath;
+            }
+
+            // 如果文件小于等于200KB,直接返回原路径
+            if (originalFile.length() <= TARGET_SIZE) {
+                log.info("文件大小 {} 字节,小于等于目标大小,无需压缩", originalFile.length());
+                System.out.println("文件大小 " + originalFile.length() + " 字节,小于等于目标大小,无需压缩");
+                return webPath;
+            }
+
+            // 生成压缩后的本地文件路径
+            String compressedLocalPath = generateCompressedLocalPath(localPath);
+            log.debug("生成压缩后本地路径: {}", compressedLocalPath);
+            System.out.println("生成压缩后本地路径: " + compressedLocalPath);
+
+            // 执行压缩
+            log.info("开始压缩图片: {} -> {}", localPath, compressedLocalPath);
+            System.out.println("开始压缩图片: " + localPath + " -> " + compressedLocalPath);
+
+            if (compressImageWithThumbnailator(localPath, compressedLocalPath)) {
+                // 将压缩后的本地路径转换为Web访问路径
+                String compressedWebPath = convertLocalPathToWebPath(compressedLocalPath);
+//                String compressedWebPath = compressedLocalPath;
+                log.info("图片压缩成功: {} -> {}", webPath, compressedWebPath);
+                System.out.println("图片压缩成功: " + webPath + " -> " + compressedWebPath);
+                return compressedWebPath;
+            } else {
+                log.warn("图片压缩失败,返回原始路径: {}", webPath);
+                System.out.println("图片压缩失败,返回原始路径: " + webPath);
+                return webPath;
+            }
+
+        } catch (Exception e) {
+            log.error("处理Web路径图片压缩时发生异常: " + webPath, e);
+            System.err.println("处理Web路径图片压缩时发生异常: " + webPath + ", 错误: " + e.getMessage());
+            e.printStackTrace();
+            return webPath;
+        } finally {
+            // 建议垃圾回收
+            System.gc();
+        }
+    }
+
+    /**
+     * 压缩图片 - 根据本地文件路径
+     *
+     * @param localPath 本地文件路径
+     * @return 压缩后的本地文件路径,如果不需要压缩则返回原路径
+     */
+    public static String compressImageByLocalPath(String localPath) {
+        log.info("开始处理本地路径图片压缩: {}", localPath);
+        System.out.println("开始处理本地路径图片压缩: " + localPath);
+
+        if (StringUtils.isEmpty(localPath)) {
+            log.warn("本地路径为空,直接返回");
+            System.out.println("本地路径为空,直接返回");
+            return localPath;
+        }
+
+        File originalFile = new File(localPath);
+        if (!originalFile.exists() || !originalFile.isFile()) {
+            log.warn("文件不存在或不是文件: {}", localPath);
+            System.out.println("文件不存在或不是文件: " + localPath);
+            return localPath;
+        }
+
+        // 如果文件小于等于200KB,直接返回原路径
+        if (originalFile.length() <= TARGET_SIZE) {
+            log.info("文件大小 {} 字节,小于等于目标大小 {} 字节,无需压缩", originalFile.length(), TARGET_SIZE);
+            System.out.println("文件大小 " + originalFile.length() + " 字节,小于等于目标大小 " + TARGET_SIZE + " 字节,无需压缩");
+            return localPath;
+        }
+
+        try {
+            // 生成压缩后的文件路径
+            String compressedPath = generateCompressedLocalPath(localPath);
+            log.debug("生成压缩后路径: {}", compressedPath);
+            System.out.println("生成压缩后路径: " + compressedPath);
+
+            // 执行压缩
+            log.info("开始压缩图片: {} -> {}", localPath, compressedPath);
+            System.out.println("开始压缩图片: " + localPath + " -> " + compressedPath);
+
+            if (compressImageWithThumbnailator(localPath, compressedPath)) {
+                log.info("本地图片压缩成功: {} -> {}", localPath, compressedPath);
+                System.out.println("本地图片压缩成功: " + localPath + " -> " + compressedPath);
+                return compressedPath;
+            } else {
+                log.warn("本地图片压缩失败,返回原始路径: {}", localPath);
+                System.out.println("本地图片压缩失败,返回原始路径: " + localPath);
+                return localPath;
+            }
+
+        } catch (Exception e) {
+            log.error("处理本地路径图片压缩时发生异常: " + localPath, e);
+            System.err.println("处理本地路径图片压缩时发生异常: " + localPath + ", 错误: " + e.getMessage());
+            e.printStackTrace();
+            return localPath;
+        } finally {
+            System.gc();
+        }
+    }
+
+    /**
+     * 压缩图片 - 简单方法,传入图片路径,返回压缩后的路径
+     *
+     * @param imagePath 图片路径
+     * @return 压缩后的图片路径,如果不需要压缩则返回原路径
+     */
+    public static String compressImage(String imagePath) {
+        log.info("开始压缩图片: {}", imagePath);
+        System.out.println("开始压缩图片: " + imagePath);
+
+        if (StringUtils.isEmpty(imagePath)) {
+            log.warn("图片路径为空");
+            System.out.println("图片路径为空");
+            return imagePath;
+        }
+
+        // 检查文件是否存在
+        File imageFile = new File(imagePath);
+        if (!imageFile.exists() || !imageFile.isFile()) {
+            log.warn("图片文件不存在: {}", imagePath);
+            System.out.println("图片文件不存在: " + imagePath);
+            return imagePath;
+        }
+
+        // 获取文件大小
+        long fileSize = imageFile.length();
+        long fileSizeKB = fileSize / 1024;
+        log.info("图片文件大小: {} 字节 ({} KB)", fileSize, fileSizeKB);
+        System.out.println("图片文件大小: " + fileSize + " 字节 (" + fileSizeKB + " KB)");
+
+        // 如果文件小于等于200KB,直接返回原路径
+        if (fileSize <= TARGET_SIZE) {
+            log.info("文件大小 {} KB,小于等于200KB,无需压缩", fileSizeKB);
+            System.out.println("文件大小 " + fileSizeKB + " KB,小于等于200KB,无需压缩");
+            return imagePath;
+        }
+
+        log.info("文件大小 {} KB,大于200KB,开始压缩", fileSizeKB);
+        System.out.println("文件大小 " + fileSizeKB + " KB,大于200KB,开始压缩");
+
+        // 调用本地路径压缩方法
+        return compressImageByLocalPath(imagePath);
+    }
+
+    /**
+     * 将Web访问路径转换为本地文件路径
+     *
+     * @param webPath Web路径 (如: /profile/upload/2025/08/05/image.jpg)
+     * @return 本地文件路径 (如: /www/wwwroot/server/uploadPath/upload/2025/08/05/image.jpg)
+     */
+    private static String convertWebPathToLocalPath(String webPath) {
+        log.debug("转换Web路径到本地路径: {}", webPath);
+        System.out.println("转换Web路径到本地路径: " + webPath);
+
+        if (StringUtils.isEmpty(webPath)) {
+            return null;
+        }
+
+        // 检查是否是有效的资源路径
+        if (!webPath.startsWith(Constants.RESOURCE_PREFIX + "/")) {
+            log.warn("不是有效的资源路径: {}", webPath);
+            System.out.println("不是有效的资源路径: " + webPath);
+            return null;
+        }
+
+        // 移除资源前缀,获取相对路径
+        String relativePath = webPath.substring(Constants.RESOURCE_PREFIX.length() + 1);
+        log.debug("相对路径: {}", relativePath);
+        System.out.println("相对路径: " + relativePath);
+
+        // 策略1: 使用配置的profile路径
+        String profilePath = RuoYiConfig.getProfile();
+
+            String localPath = Paths.get(profilePath, relativePath).toString();
+            log.debug("策略1 - 使用profile路径: {} -> {}", profilePath, localPath);
+            System.out.println("策略1 - 使用profile路径: " + profilePath + " -> " + localPath);
+
+            // 检查文件是否存在
+            File file = new File(localPath);
+            if (file.exists()) {
+                log.debug("策略1成功 - 文件存在: {}", localPath);
+                System.out.println("策略1成功 - 文件存在: " + localPath);
+                return localPath;
+            } else {
+                log.debug("策略1失败 - 文件不存在: {}", localPath);
+                System.out.println("策略1失败 - 文件不存在: " + localPath);
+            }
+            return null;
+    }
+
+    /**
+     * 将本地文件路径转换为Web访问路径
+     *
+     * @param localPath 本地文件路径
+     * @return Web访问路径
+     */
+    private static String convertLocalPathToWebPath(String localPath) {
+        // 步骤1:统一替换路径分隔符为正斜杠(兼容所有系统)
+        if (StringUtils.isEmpty(localPath)) return null;
+        String normalizedPath = localPath.replace("\\", "/");  // 关键点1:统一使用/
+
+        log.debug("转换本地路径到Web路径: {}", normalizedPath);
+        String profilePath = RuoYiConfig.getProfile();
+        if (profilePath != null) {
+            profilePath = profilePath.replace("\\", "/");  // 关键点2:配置路径也统一
+        }
+
+        // 步骤2:优化路径匹配逻辑(使用统一的分隔符)
+        String webPath = null;
+        // 策略1: 检查配置目录
+        if (profilePath != null && normalizedPath.startsWith(profilePath)) {
+            int startIndex = profilePath.endsWith("/") ?
+                    profilePath.length() :
+                    profilePath.length() + 1;
+            String relativePath = normalizedPath.substring(startIndex);
+            webPath = Constants.RESOURCE_PREFIX + "/" + relativePath;
+            log.debug("策略1成功 - Web路径: {}", webPath);
+        }
+        // 策略2: 处理含upload的路径
+        else if (normalizedPath.contains("/upload/")) {
+            int uploadIndex = normalizedPath.indexOf("/upload/") + 1;
+            webPath = Constants.RESOURCE_PREFIX + "/" + normalizedPath.substring(uploadIndex);
+            log.debug("策略2成功 - Web路径: {}", webPath);
+        }
+        // 策略3: 兜底方案(文件名直用)
+        else {
+            int lastSlash = normalizedPath.lastIndexOf("/");
+            String fileName = (lastSlash != -1) ?
+                    normalizedPath.substring(lastSlash + 1) :
+                    normalizedPath;
+            webPath = Constants.RESOURCE_PREFIX + "/upload/" + fileName;
+            log.debug("策略3成功 - Web路径: {}", webPath);
+        }
+
+        // 步骤3:确保结果有效性
+        if (webPath != null) {
+            log.info("转换成功: {} → {}", normalizedPath, webPath);
+            return webPath;
+        } else {
+            log.error("转换失败: {}", normalizedPath);
+            return null;
+        }
+    }
+
+    /**
+     * 使用Thumbnailator压缩图片
+     *
+     * @param inputPath  输入路径
+     * @param outputPath 输出路径
+     * @return 是否压缩成功
+     */
+    private static boolean compressImageWithThumbnailator(String inputPath, String outputPath) {
+        log.info("使用Thumbnailator压缩图片: {} -> {}", inputPath, outputPath);
+        System.out.println("使用Thumbnailator压缩图片: " + inputPath + " -> " + outputPath);
+
+        try {
+            // 确保输出目录存在
+            File outputFile = new File(outputPath);
+            File parentDir = outputFile.getParentFile();
+            if (!parentDir.exists()) {
+                log.debug("创建输出目录: {}", parentDir.getAbsolutePath());
+                System.out.println("创建输出目录: " + parentDir.getAbsolutePath());
+                parentDir.mkdirs();
+            }
+
+            // 使用二分法查找合适的压缩质量
+            log.debug("查找最优压缩质量");
+            System.out.println("查找最优压缩质量");
+            float quality = findOptimalQuality(inputPath, outputPath);
+
+            // 执行最终压缩
+            log.debug("执行最终压缩,质量: {}", quality);
+            System.out.println("执行最终压缩,质量: " + quality);
+            Thumbnails.of(inputPath)
+                    .scale(1.0f) // 保持原尺寸
+                    .outputQuality(quality) // 设置压缩质量
+                    .toFile(outputPath);
+
+            // 检查压缩后的文件大小
+            File compressedFile = new File(outputPath);
+            boolean success = compressedFile.exists() && compressedFile.length() <= TARGET_SIZE;
+            log.info("压缩完成,文件存在: {}, 文件大小: {} 字节, 压缩成功: {}",
+                    compressedFile.exists(), compressedFile.length(), success);
+            System.out.println("压缩完成,文件存在: " + compressedFile.exists() +
+                    ", 文件大小: " + compressedFile.length() + " 字节, 压缩成功: " + success);
+            return success;
+
+        } catch (IOException e) {
+            log.error("压缩图片时发生IO异常: " + inputPath, e);
+            System.err.println("压缩图片时发生IO异常: " + inputPath + ", 错误: " + e.getMessage());
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 使用二分法查找最优压缩质量
+     */
+    private static float findOptimalQuality(String inputPath, String outputPath) {
+        log.debug("使用二分法查找最优压缩质量: {}", inputPath);
+        System.out.println("使用二分法查找最优压缩质量: " + inputPath);
+
+        float minQuality = 0.1f;
+        float maxQuality = 1.0f;
+        float bestQuality = 0.8f;
+
+        // 创建临时文件用于测试
+        String tempPath = generateTempPath(outputPath);
+        log.debug("创建临时文件用于测试: {}", tempPath);
+        System.out.println("创建临时文件用于测试: " + tempPath);
+
+        try {
+            // 确保临时文件目录存在
+            File tempFile = new File(tempPath);
+            File parentDir = tempFile.getParentFile();
+            if (!parentDir.exists()) {
+                log.debug("创建临时文件目录: {}", parentDir.getAbsolutePath());
+                System.out.println("创建临时文件目录: " + parentDir.getAbsolutePath());
+                parentDir.mkdirs();
+            }
+
+            // 二分查找最优质量值
+            for (int i = 0; i < 10; i++) { // 减少迭代次数,提高效率
+                float testQuality = (minQuality + maxQuality) / 2;
+                log.debug("第{}次测试,压缩质量: {}", i + 1, testQuality);
+                System.out.println("第" + (i + 1) + "次测试,压缩质量: " + testQuality);
+
+                try {
+                    // 确保临时文件不存在
+                    if (tempFile.exists()) {
+                        tempFile.delete();
+                    }
+
+                    // 测试当前质量的文件大小
+                    Thumbnails.of(inputPath)
+                            .scale(1.0f)
+                            .outputQuality(testQuality)
+                            .toFile(tempPath);
+
+                    // 等待文件写入完成
+                    Thread.sleep(100);
+
+                    long fileSize = tempFile.length();
+                    log.debug("测试结果 - 文件大小: {} 字节, 目标大小: {} 字节", fileSize, TARGET_SIZE);
+                    System.out.println("测试结果 - 文件大小: " + fileSize + " 字节, 目标大小: " + TARGET_SIZE + " 字节");
+
+                    if (fileSize <= TARGET_SIZE) {
+                        bestQuality = testQuality;
+                        minQuality = testQuality;
+                        log.debug("文件大小符合要求,调整最小质量为: {}", minQuality);
+                        System.out.println("文件大小符合要求,调整最小质量为: " + minQuality);
+                    } else {
+                        maxQuality = testQuality;
+                        log.debug("文件大小超过目标,调整最大质量为: {}", maxQuality);
+                        System.out.println("文件大小超过目标,调整最大质量为: " + maxQuality);
+                    }
+
+                    // 如果已经很接近目标大小,提前退出
+                    if (Math.abs(fileSize - TARGET_SIZE) < 10240) { // 10KB的容差
+                        bestQuality = testQuality;
+                        log.info("已接近目标大小,提前退出,最优质量: {}", bestQuality);
+                        System.out.println("已接近目标大小,提前退出,最优质量: " + bestQuality);
+                        break;
+                    }
+
+                    // 如果质量范围已经很小,提前退出
+                    if (Math.abs(maxQuality - minQuality) < 0.05f) {
+                        log.info("质量范围已经很小,提前退出,最优质量: {}", bestQuality);
+                        System.out.println("质量范围已经很小,提前退出,最优质量: " + bestQuality);
+                        break;
+                    }
+
+                } catch (IOException e) {
+                    log.warn("测试压缩质量 {} 时出现异常: {}", testQuality, e.getMessage());
+                    System.out.println("测试压缩质量 " + testQuality + " 时出现异常: " + e.getMessage());
+                    // 如果当前质量测试失败,调整范围继续测试
+                    maxQuality = testQuality;
+                    continue;
+                } catch (InterruptedException e) {
+                    log.warn("等待文件写入时被中断");
+                    System.out.println("等待文件写入时被中断");
+                    Thread.currentThread().interrupt();
+                    break;
+                }
+
+                // 删除临时文件
+                if (tempFile.exists()) {
+                    tempFile.delete();
+                }
+            }
+        } catch (Exception e) {
+            log.error("查找最优压缩质量时发生异常", e);
+            System.err.println("查找最优压缩质量时发生异常: " + e.getMessage());
+            e.printStackTrace();
+            // 如果出错,使用默认质量
+            bestQuality = 0.6f;
+        } finally {
+            // 清理可能残留的临时文件
+            File tempFile = new File(tempPath);
+            if (tempFile.exists()) {
+                log.debug("清理残留临时文件: {}", tempPath);
+                System.out.println("清理残留临时文件: " + tempPath);
+                tempFile.delete();
+            }
+        }
+
+        log.info("最优压缩质量查找完成: {}", bestQuality);
+        System.out.println("最优压缩质量查找完成: " + bestQuality);
+        return bestQuality;
+    }
+
+    /**
+     * 生成临时文件路径,保持正确的图片扩展名
+     *
+     * @param outputPath 输出文件路径
+     * @return 临时文件路径
+     */
+    private static String generateTempPath(String outputPath) {
+        File outputFile = new File(outputPath);
+        String fileName = outputFile.getName();
+        String parentDir = outputFile.getParent();
+
+        int dotIndex = fileName.lastIndexOf('.');
+        if (dotIndex == -1) {
+            // 没有扩展名,默认添加.jpg
+            return Paths.get(parentDir, fileName + "_comp.jpg").toString();
+        } else {
+            String nameWithoutExt = fileName.substring(0, dotIndex);
+            String extension = fileName.substring(dotIndex);
+            return Paths.get(parentDir, nameWithoutExt + "_comp" + extension).toString();
+        }
+    }
+
+    /**
+     * 生成压缩后的本地文件路径(在同一目录下)
+     *
+     * @param originalPath 原文件路径
+     * @return 压缩后的文件路径
+     */
+    private static String generateCompressedLocalPath(String originalPath) {
+        log.debug("生成压缩后本地文件路径: {}", originalPath);
+        System.out.println("生成压缩后本地文件路径: " + originalPath);
+
+        File originalFile = new File(originalPath);
+        String parentDir = originalFile.getParent();
+        String fileName = originalFile.getName();
+
+        int dotIndex = fileName.lastIndexOf('.');
+        String compressedPath;
+        if (dotIndex == -1) {
+            compressedPath = Paths.get(parentDir, fileName + "_comp.jpg").toString();
+        } else {
+            String nameWithoutExt = fileName.substring(0, dotIndex);
+            String extension = fileName.substring(dotIndex);
+
+            // 对于PNG文件,转换为JPG以获得更好的压缩效果
+            if (".png".equalsIgnoreCase(extension)) {
+                extension = ".jpg";
+            }
+
+            String compressedFileName = nameWithoutExt + "_comp" + extension;
+            compressedPath = Paths.get(parentDir, compressedFileName).toString();
+        }
+
+        log.debug("生成的压缩文件路径: {}", compressedPath);
+        System.out.println("生成的压缩文件路径: " + compressedPath);
+        return compressedPath;
+    }
+
+    /**
+     * 批量压缩图片(Web路径)
+     *
+     * @param webPaths Web访问路径数组
+     * @return 压缩后的Web访问路径数组
+     */
+    public static String[] compressImagesByWebPath(String[] webPaths) {
+        log.info("批量压缩图片,数量: {}", webPaths != null ? webPaths.length : 0);
+        System.out.println("批量压缩图片,数量: " + (webPaths != null ? webPaths.length : 0));
+
+        if (webPaths == null) {
+            log.warn("Web路径数组为空");
+            System.out.println("Web路径数组为空");
+            return null;
+        }
+
+        String[] compressedPaths = new String[webPaths.length];
+        for (int i = 0; i < webPaths.length; i++) {
+            log.debug("批量压缩第{}张图片: {}", i + 1, webPaths[i]);
+            System.out.println("批量压缩第" + (i + 1) + "张图片: " + webPaths[i]);
+            compressedPaths[i] = compressImageByWebPath(webPaths[i]);
+        }
+
+        log.info("批量压缩完成");
+        System.out.println("批量压缩完成");
+        return compressedPaths;
+    }
+
+    /**
+     * 检查路径是否为若依资源路径
+     *
+     * @param path 路径
+     * @return 是否为资源路径
+     */
+    public static boolean isResourcePath(String path) {
+        boolean result = StringUtils.isNotEmpty(path) && path.startsWith(Constants.RESOURCE_PREFIX + "/");
+        log.debug("检查是否为资源路径: {} -> {}", path, result);
+        System.out.println("检查是否为资源路径: " + path + " -> " + result);
+        return result;
+    }
+
+    /**
+     * 获取文件大小(字节)
+     *
+     * @param webPath Web访问路径
+     * @return 文件大小,如果文件不存在返回-1
+     */
+    public static long getFileSize(String webPath) {
+        log.debug("获取文件大小: {}", webPath);
+        System.out.println("获取文件大小: " + webPath);
+
+        String localPath = convertWebPathToLocalPath(webPath);
+        if (StringUtils.isEmpty(localPath)) {
+            log.warn("无法转换Web路径到本地路径");
+            System.out.println("无法转换Web路径到本地路径");
+            return -1;
+        }
+
+        File file = new File(localPath);
+        long fileSize = file.exists() ? file.length() : -1;
+        log.debug("文件大小: {} 字节", fileSize);
+        System.out.println("文件大小: " + fileSize + " 字节");
+        return fileSize;
+    }
+
+
+}

+ 195 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/IpUtils.java

@@ -0,0 +1,195 @@
+package com.ruoyi.app.utils;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.*;
+import java.util.Enumeration;
+
+/**
+ *@Author: make mpy
+ *@Description: 获取IP的方法
+ *@Date: 2021/1/18 15:02
+ */
+@Slf4j
+public class IpUtils {
+    private static final String LOCAL_IP = "127.0.0.1";
+    /**
+     * 获取IP地址
+     *
+     * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
+     * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
+     */
+    public static String getIpAddr(HttpServletRequest request) {
+        if (request == null) {
+            return "unknown";
+        }
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Forwarded-For");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Real-IP");
+        }
+
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+
+        return "0:0:0:0:0:0:0:1".equals(ip) ? LOCAL_IP : ip;
+    }
+
+    public static boolean internalIp(String ip) {
+        boolean res = false;
+        byte[] addr = textToNumericFormatV4(ip);
+        if (addr != null && ip != null) {
+            res = internalIp(addr) || LOCAL_IP.equals(ip);
+        }
+        return res;
+    }
+
+    private static boolean internalIp(byte[] addr) {
+        final byte b0 = addr[0];
+        final byte b1 = addr[1];
+        // 10.x.x.x/8
+        final byte SECTION_1 = 0x0A;
+        // 172.16.x.x/12
+        final byte SECTION_2 = (byte) 0xAC;
+        final byte SECTION_3 = (byte) 0x10;
+        final byte SECTION_4 = (byte) 0x1F;
+        // 192.168.x.x/16
+        final byte SECTION_5 = (byte) 0xC0;
+        final byte SECTION_6 = (byte) 0xA8;
+        boolean flag = false;
+        switch (b0) {
+            case SECTION_1:
+                flag = true;
+                break;
+            case SECTION_2:
+                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
+                    flag = true;
+                }
+                break;
+            case SECTION_5:
+                if (b1 == SECTION_6) {
+                    flag = true;
+                }
+                break;
+            default:
+                break;
+        }
+        return flag;
+    }
+
+    /**
+     * 将IPv4地址转换成字节
+     *IPv4地址
+     * @param text
+     * @return byte 字节
+     */
+    public static byte[] textToNumericFormatV4(String text) {
+        if (text.length() == 0) {
+            return null;
+        }
+
+        byte[] bytes = new byte[4];
+        String[] elements = text.split("\\.", -1);
+        try {
+            long l;
+            int i;
+            switch (elements.length) {
+                case 1:
+                    l = Long.parseLong(elements[0]);
+                    if ((l < 0L) || (l > 4294967295L))
+                        return null;
+                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 2:
+                    l = Integer.parseInt(elements[0]);
+                    if ((l < 0L) || (l > 255L))
+                        return null;
+                    bytes[0] = (byte) (int) (l & 0xFF);
+                    l = Integer.parseInt(elements[1]);
+                    if ((l < 0L) || (l > 16777215L))
+                        return null;
+                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 3:
+                    for (i = 0; i < 2; ++i) {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L))
+                            return null;
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    l = Integer.parseInt(elements[2]);
+                    if ((l < 0L) || (l > 65535L))
+                        return null;
+                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 4:
+                    for (i = 0; i < 4; ++i) {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L))
+                            return null;
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    break;
+                default:
+                    return null;
+            }
+        } catch (NumberFormatException e) {
+            log.error("数字格式化异常",e);
+            return null;
+        }
+        return bytes;
+    }
+
+    public static String getLocalIP() {
+        String ip = "";
+        if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
+            InetAddress addr;
+            try {
+                addr = InetAddress.getLocalHost();
+                ip = addr.getHostAddress();
+            } catch (UnknownHostException e) {
+                log.error("获取失败",e);
+            }
+            return ip;
+        } else {
+            try {
+                Enumeration<?> e1 = (Enumeration<?>) NetworkInterface
+                        .getNetworkInterfaces();
+                while (e1.hasMoreElements()) {
+                    NetworkInterface ni = (NetworkInterface) e1.nextElement();
+                    if (!ni.getName().equals("eth0")) {
+                        continue;
+                    } else {
+                        Enumeration<?> e2 = ni.getInetAddresses();
+                        while (e2.hasMoreElements()) {
+                            InetAddress ia = (InetAddress) e2.nextElement();
+                            if (ia instanceof Inet6Address)
+                                continue;
+                            ip = ia.getHostAddress();
+                            return ip;
+                        }
+                        break;
+                    }
+                }
+            } catch (SocketException e) {
+                log.error("获取失败",e);
+            }
+        }
+        return "";
+    }
+}

+ 271 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/Md5Pay.java

@@ -0,0 +1,271 @@
+package com.ruoyi.app.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.system.domain.vo.PayResponse;
+import com.ruoyi.system.domain.vo.PayVN;
+import lombok.SneakyThrows;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class Md5Pay {
+    public static final SimpleDateFormat ymdhms = new SimpleDateFormat("yyyyMMddHHmmss");
+
+//    public JSONObject payMd5(String orderid,String amount,String customName){
+//        try {
+//            String merchantNo = "API8918130442359667";
+//            String merchant_private_key = "6d75bb6318944312b7456193ce776a6f";
+//            String signType = "MD5";
+//            String url = "https://mgp-pay.com:8443/api/pay/V2";
+//
+//            Map<String, String> requestMap = new HashMap<String, String>();
+//            requestMap.put("merchantNo", merchantNo);
+//            requestMap.put("channleType", "1");
+//            requestMap.put("signType", signType);
+//            requestMap.put("version", "V2");// 常量V1
+//            requestMap.put("date", ymdhms.format(new Date()));
+//            requestMap.put("orderNo", orderid);// System.currentTimeMillis()
+//            requestMap.put("bizAmt", amount); // 元
+//            requestMap.put("customName", customName); // 元
+//            requestMap.put("noticeUrl", "http://203.175.169.46:8080/pay/payJson");
+//            String signStr = SftSignUtil.formatSignData(requestMap);
+//            System.out.println("signStr签名:" + signStr);
+//            String sign = SftSignUtil.sign(signType, signStr, merchant_private_key);
+//            requestMap.put("sign", sign);
+//            System.out.println("sign  "+sign);
+//            Map<String, String> head = new HashMap<String, String>();
+//            head.put("Content-Type", "application/json");
+//            String rs = HttpKit.post(url, JSON.toJSONString(requestMap), head);
+//            JSONObject jsonObject = JSONObject.parseObject(rs);
+//            return  jsonObject;
+//        } catch (Exception e) {
+//            JSONObject json = new JSONObject();
+//            json.put("data",null);
+//            return json;
+//        }
+//    }
+
+    //发起支付
+    @SneakyThrows
+    public String VNPay(String language, String orderid, String amount,String ip){
+        String vnp_Version = "2.1.0";
+        String vnp_Command = "pay";
+        String orderType = "other";
+        String bankCode = "";
+        long pamount = Long.valueOf(amount)*100;
+
+        String vnp_TxnRef = VNPay.getRandomNumber(8);
+        String vnp_IpAddr = ip;
+
+        String vnp_TmnCode = VNPay.vnp_TmnCode;
+
+        Map<String, String> vnp_Params = new HashMap<>();
+        vnp_Params.put("vnp_Version", vnp_Version);
+        vnp_Params.put("vnp_Command", vnp_Command);
+        vnp_Params.put("vnp_TmnCode", vnp_TmnCode);
+        vnp_Params.put("vnp_Amount", String.valueOf(pamount));
+        vnp_Params.put("vnp_CurrCode", "VND");
+
+        if (bankCode != null && !bankCode.isEmpty()) {
+            vnp_Params.put("vnp_BankCode", bankCode);
+        }
+        vnp_Params.put("vnp_TxnRef", orderid);
+        vnp_Params.put("vnp_OrderInfo", orderid);
+        vnp_Params.put("vnp_OrderType", orderType);
+
+        String locate = language;
+        if (locate != null && !locate.isEmpty()) {
+            vnp_Params.put("vnp_Locale", locate);
+        } else {
+            vnp_Params.put("vnp_Locale", "vn");
+        }
+        vnp_Params.put("vnp_ReturnUrl", VNPay.vnp_ReturnUrl);
+        vnp_Params.put("vnp_IpAddr", vnp_IpAddr);
+
+        Calendar cld = Calendar.getInstance(TimeZone.getTimeZone("Etc/GMT+7"));
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        String vnp_CreateDate = formatter.format(cld.getTime());
+        vnp_Params.put("vnp_CreateDate", vnp_CreateDate);
+
+        cld.add(Calendar.MINUTE, 15);
+        String vnp_ExpireDate = formatter.format(cld.getTime());
+        vnp_Params.put("vnp_ExpireDate", vnp_ExpireDate);
+
+        List fieldNames = new ArrayList(vnp_Params.keySet());
+        Collections.sort(fieldNames);
+        StringBuilder hashData = new StringBuilder();
+        StringBuilder query = new StringBuilder();
+        Iterator itr = fieldNames.iterator();
+        while (itr.hasNext()) {
+            String fieldName = (String) itr.next();
+            String fieldValue = (String) vnp_Params.get(fieldName);
+            if ((fieldValue != null) && (fieldValue.length() > 0)) {
+                //Build hash data
+                hashData.append(fieldName);
+                hashData.append('=');
+                hashData.append(URLEncoder.encode(fieldValue, StandardCharsets.US_ASCII.toString()));
+                //Build query
+                query.append(URLEncoder.encode(fieldName, StandardCharsets.US_ASCII.toString()));
+                query.append('=');
+                query.append(URLEncoder.encode(fieldValue, StandardCharsets.US_ASCII.toString()));
+                if (itr.hasNext()) {
+                    query.append('&');
+                    hashData.append('&');
+                }
+            }
+        }
+        String queryUrl = query.toString();
+        String vnp_SecureHash = VNPay.hmacSHA512(VNPay.secretKey, hashData.toString());
+        queryUrl += "&vnp_SecureHash=" + vnp_SecureHash;
+        String paymentUrl = VNPay.vnp_PayUrl + "?" + queryUrl;
+
+        return paymentUrl;
+    }
+    //查询支付订单
+    public String getPay(PayResponse payResponse,String  ip) throws IOException {
+        //Command:querydr
+
+        String vnp_RequestId = VNPay.getRandomNumber(8);
+        String vnp_Version = "2.1.0";
+        String vnp_Command = "querydr";
+        String vnp_TmnCode = VNPay.vnp_TmnCode;
+        String vnp_TxnRef = payResponse.getOrder_id();
+        String vnp_OrderInfo =  vnp_TxnRef;;
+        //String vnp_TransactionNo = req.getParameter("transactionNo");
+        String vnp_TransDate = payResponse.getTrans_date();
+
+        Calendar cld = Calendar.getInstance(TimeZone.getTimeZone("Etc/GMT+7"));
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        String vnp_CreateDate = formatter.format(cld.getTime());
+
+        String vnp_IpAddr = ip;
+
+        JSONObject  vnp_Params = new JSONObject();
+
+        vnp_Params.put("vnp_RequestId", vnp_RequestId);
+        vnp_Params.put("vnp_Version", vnp_Version);
+        vnp_Params.put("vnp_Command", vnp_Command);
+        vnp_Params.put("vnp_TmnCode", vnp_TmnCode);
+        vnp_Params.put("vnp_TxnRef", vnp_TxnRef);
+        vnp_Params.put("vnp_OrderInfo", vnp_OrderInfo);
+        //vnp_Params.put("vnp_TransactionNo", vnp_TransactionNo);
+        vnp_Params.put("vnp_TransactionDate", vnp_TransDate);
+        vnp_Params.put("vnp_CreateDate", vnp_CreateDate);
+        vnp_Params.put("vnp_IpAddr", vnp_IpAddr);
+
+        String hash_Data= String.join("|", vnp_RequestId, vnp_Version, vnp_Command, vnp_TmnCode, vnp_TxnRef, vnp_TransDate, vnp_CreateDate, vnp_IpAddr, vnp_OrderInfo);
+        String vnp_SecureHash = VNPay.hmacSHA512(VNPay.secretKey, hash_Data.toString());
+
+        vnp_Params.put("vnp_SecureHash", vnp_SecureHash);
+
+        URL url = new URL (VNPay.vnp_ApiUrl);
+        HttpURLConnection con = (HttpURLConnection)url.openConnection();
+        con.setRequestMethod("POST");
+        con.setRequestProperty("Content-Type", "application/json");
+        con.setDoOutput(true);
+        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
+        wr.writeBytes(vnp_Params.toString());
+        wr.flush();
+        wr.close();
+        int responseCode = con.getResponseCode();
+        System.out.println("nSending 'POST' request to URL : " + url);
+        System.out.println("Post Data : " + vnp_Params);
+        System.out.println("Response Code : " + responseCode);
+        BufferedReader in = new BufferedReader(
+                new InputStreamReader(con.getInputStream()));
+        String output;
+        StringBuffer response = new StringBuffer();
+        while ((output = in.readLine()) != null) {
+            response.append(output);
+        }
+        in.close();
+        System.out.println(response.toString());
+        return response.toString();
+    }
+
+   //退款
+   public String doPost(PayVN payVN) throws IOException {
+
+        //Command: refund
+        String vnp_RequestId = VNPay.getRandomNumber(8);
+        String vnp_Version = "2.1.0";
+        String vnp_Command = "refund";
+        String vnp_TmnCode = VNPay.vnp_TmnCode;
+        String vnp_TransactionType = payVN.getTrantype();
+        String vnp_TxnRef =  payVN.getOrder_id();
+        long amount = Integer.parseInt(payVN.getAmount())*100;
+        String vnp_Amount = String.valueOf(amount);
+        String vnp_OrderInfo = vnp_TxnRef;
+        String vnp_TransactionNo = payVN.getTransaction(); //不存在则为空。
+        String vnp_TransactionDate = payVN.getTrans_date();
+        String vnp_CreateBy = payVN.getUser();
+
+        Calendar cld = Calendar.getInstance(TimeZone.getTimeZone("Etc/GMT+7"));
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+        String vnp_CreateDate = formatter.format(cld.getTime());
+
+        String vnp_IpAddr = payVN.getIpaddr();
+
+        JSONObject  vnp_Params = new JSONObject ();
+
+        vnp_Params.put("vnp_RequestId", vnp_RequestId);
+        vnp_Params.put("vnp_Version", vnp_Version);
+        vnp_Params.put("vnp_Command", vnp_Command);
+        vnp_Params.put("vnp_TmnCode", vnp_TmnCode);
+        vnp_Params.put("vnp_TransactionType", vnp_TransactionType);
+        vnp_Params.put("vnp_TxnRef", vnp_TxnRef);
+        vnp_Params.put("vnp_Amount", vnp_Amount);
+        vnp_Params.put("vnp_OrderInfo", vnp_OrderInfo);
+
+        if(vnp_TransactionNo != null && !vnp_TransactionNo.isEmpty())
+        {
+            vnp_Params.put("vnp_TransactionNo", payVN.getTransaction());
+        }
+
+        vnp_Params.put("vnp_TransactionDate", vnp_TransactionDate);
+        vnp_Params.put("vnp_CreateBy", vnp_CreateBy);
+        vnp_Params.put("vnp_CreateDate", vnp_CreateDate);
+        vnp_Params.put("vnp_IpAddr", vnp_IpAddr);
+
+        String hash_Data= String.join("|", vnp_RequestId, vnp_Version, vnp_Command, vnp_TmnCode,
+                vnp_TransactionType, vnp_TxnRef, vnp_Amount, vnp_TransactionNo, vnp_TransactionDate,
+                vnp_CreateBy, vnp_CreateDate, vnp_IpAddr, vnp_OrderInfo);
+
+        String vnp_SecureHash = VNPay.hmacSHA512(VNPay.secretKey, hash_Data.toString());
+
+        vnp_Params.put("vnp_SecureHash", vnp_SecureHash);
+
+        URL url = new URL (VNPay.vnp_ApiUrl);
+        HttpURLConnection con = (HttpURLConnection)url.openConnection();
+        con.setRequestMethod("POST");
+        con.setRequestProperty("Content-Type", "application/json");
+        con.setDoOutput(true);
+        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
+        wr.writeBytes(vnp_Params.toString());
+        wr.flush();
+        wr.close();
+        int responseCode = con.getResponseCode();
+        System.out.println("nSending 'POST' request to URL : " + url);
+        System.out.println("Post Data : " + vnp_Params);
+        System.out.println("Response Code : " + responseCode);
+        BufferedReader in = new BufferedReader(
+                new InputStreamReader(con.getInputStream()));
+        String output;
+        StringBuffer response = new StringBuffer();
+        while ((output = in.readLine()) != null) {
+            response.append(output);
+        }
+        in.close();
+        System.out.println(response.toString());
+        return response.toString();
+    }
+}

+ 169 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/PayMD5.java

@@ -0,0 +1,169 @@
+package com.ruoyi.app.utils;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.UUID;
+
+//~--- classes ----------------------------------------------------------------
+
+/**
+ * Class MD5
+ * Description
+ * Create 2016-02-25 01:03:21
+ * @author Ardy
+ */
+public class PayMD5 {
+
+    /**
+     * Field hexDigits
+     * Description
+     */
+    private final static String[] hexDigits = {
+            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"
+    };
+
+    /**
+     * Method byteArrayToHexString
+     * Description 说明:
+     *
+     * @param b 说明:
+     *
+     * @return 返回值说明:
+     */
+    public static String byteArrayToHexString(byte[] b) {
+        StringBuilder resultSb = new StringBuilder();
+
+        for (byte aB : b) {
+            resultSb.append(byteToHexString(aB));
+        }
+
+        return resultSb.toString();
+    }
+
+    /**
+     * Method byteToHexString
+     * Description 说明:
+     *
+     * @param b 说明:
+     *
+     * @return 返回值说明:
+     */
+    private static String byteToHexString(byte b) {
+        int n = b;
+
+        if (n < 0) {
+            n += 256;
+        }
+
+        int d1 = n >>> 4;
+        int d2 = n % 16;
+
+        return hexDigits[d1] + hexDigits[d2];
+    }
+
+    /**
+     * Method MD5Encode
+     * Description 说明:
+     *
+     * @param origin 说明:
+     *
+     * @return 返回值说明:
+     */
+    public static String MD5Encode(String origin) {
+        String resultString = null;
+
+        try {
+            resultString = origin;
+
+            MessageDigest md = MessageDigest.getInstance("MD5");
+
+            resultString = byteArrayToHexString(md.digest(resultString.getBytes("utf-8")));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return resultString;
+    }
+
+    /**
+     * Method md5
+     * Description 说明:
+     *
+     * @param password 说明:
+     *
+     * @return 返回值说明:
+     *
+     * @throws NoSuchAlgorithmException 异常:
+     */
+    public static String md5(String password) throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+
+        md.update(password.getBytes());
+
+        return new BigInteger(1, md.digest()).toString(16);
+    }
+
+    /**
+     * Method md5
+     * Description 说明:
+     *
+     * @param username 说明:
+     * @param password 说明:
+     *
+     * @return 返回值说明:
+     *
+     * @throws NoSuchAlgorithmException 异常:
+     */
+    public static String md5(String username, String password) throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+
+        md.update(username.getBytes());
+        md.update(password.getBytes());
+
+        return new BigInteger(1, md.digest()).toString(16);
+    }
+
+    public static String md5T16(){
+        String uuid = String.valueOf(UUID.randomUUID());
+        return md5T16(uuid);
+    }
+
+    public static String md5T16(String origin){
+        return  MD5Encode(origin).substring(8, 24);
+    }
+    /**
+     * Method main
+     * Description 说明:
+     *
+     * @param args 说明:
+     */
+    public static void main(String[] args) throws NoSuchAlgorithmException {
+        String aa = "";
+        String aaa= String.valueOf("1" + System.nanoTime()) + Math.ceil(Math.random() * 9 + 1) * 10000;
+        aa = md5T16();
+        String bb = md5(aaa).substring(8,24);
+        System.out.println(aa);
+        System.out.println(bb);
+        System.out.println("1"
+                + ( ( new SimpleDateFormat("yyyyMMddHHmm") ).format(new Date())
+                + Math.ceil(( Math.random() * 9 + 1 ) * 100) ));
+
+        System.out.println(String.valueOf(System.nanoTime()) + "|" + aa);
+
+        try {
+            System.out.println(md5("zhangdi", "zhangdi"));
+        } catch (NoSuchAlgorithmException e) {
+
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+
+    }
+}
+

+ 35 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/PayPush.java

@@ -0,0 +1,35 @@
+package com.ruoyi.app.utils;
+
+import cn.hutool.http.HttpUtil;
+
+public class PayPush {
+    //用户端推送
+    public void apppush(String cid,String title, String content, String body){
+        System.out.println("用户端推送cid:"+cid);
+        String url = "https://fc-mp-20ccbe79-10f8-41d7-a06c-c42581f351c1.next.bspapp.com/push?cid="+cid+
+                "&title="+title+"&content="+content+"&payload="+body;
+        String res="";
+        res = HttpUtil.get(url);
+        //JSONObject jsonObject =  JSON.parseObject(res);
+        System.out.println("=========================1111111111111111"+res);
+    }
+    //骑手端推送
+    public void qspush(String cid,String title, String content, String body){
+        String url = "https://fc-mp-20ccbe79-10f8-41d7-a06c-c42581f351c1.next.bspapp.com/ptpush?cid="+cid+
+                "&title="+title+"&content="+content+"&payload="+body+"&sound=pushsound.caf";
+        String res="";
+        res = HttpUtil.get(url);
+        //JSONObject jsonObject =  JSON.parseObject(res);
+        System.out.println("=========================用户推送"+res);
+    }
+    //商家端推送
+    public void shpush(String cid,String title, String content, String body){
+        System.out.println("商家cid:"+cid);
+        String url = "https://fc-mp-20ccbe79-10f8-41d7-a06c-c42581f351c1.next.bspapp.com/sjpush?cid="+cid+
+                "&title="+title+"&content="+content+"&payload="+body;
+        String res="";
+        res = HttpUtil.get(url);
+        //JSONObject jsonObject =  JSON.parseObject(res);
+        System.out.println("=========================商家推送"+res);
+    }
+}

+ 161 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/RSAUtil.java

@@ -0,0 +1,161 @@
+package com.ruoyi.app.utils;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import java.security.*;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+/**
+ * @author zeming.fan@swiftpass.cn
+ *
+ */
+public class RSAUtil {
+    public static enum CipherSuite {
+        ECB_PKCS1PADDING("RSA/ECB/PKCS1Padding");
+
+        private String suite;
+
+        CipherSuite(String suite) {
+            this.suite = suite;
+        }
+
+        public String val() {
+            return suite;
+        }
+    }
+
+    public static enum SignatureSuite {
+        SHA1("SHA1WithRSA"),SHA256("SHA256WithRSA");
+
+        private String suite;
+
+        SignatureSuite(String suite) {
+            this.suite = suite;
+        }
+
+        public String val() {
+            return suite;
+        }
+    }
+
+    //    private final static Logger logger = LoggerFactory.getLogger(RSAUtil.class);
+    private final static KeyFactory keyFactory;
+
+    static {
+        try {
+            keyFactory = KeyFactory.getInstance("RSA");
+        } catch (NoSuchAlgorithmException e) {
+            // 应该不会出现
+            throw new RuntimeException("初始化RSA KeyFactory失败");
+        }
+    }
+
+    public static byte[] encrypt(CipherSuite suite, byte[] msgBuf, String publicKeyStr) {
+        Cipher cipher = null;
+        try {
+            cipher = Cipher.getInstance(suite.val());
+        } catch (Exception e) {
+        }
+        try {
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
+            PublicKey publicKey = keyFactory.generatePublic(keySpec);
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        } catch(Exception e) {
+//            logger.warn("解析公钥失败:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PUBKEY");
+        }
+        try {
+            byte[] encrypted = cipher.doFinal(msgBuf);
+            return encrypted;
+        } catch (IllegalBlockSizeException e) {
+//            logger.error("加密失败,待加密消息长度过长:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PARAM");
+        } catch (Exception e) {
+//            logger.error("加密失败,未知异常:{}", e.getMessage());
+            throw new RuntimeException("UNKNOWN_EXC");
+        }
+    }
+
+    public static byte[] decrypt(CipherSuite suite, byte[] encryptedMsgBuf, String privateKeyStr) {
+        Cipher cipher = null;
+        try {
+            cipher = Cipher.getInstance(suite.val());
+        } catch (Exception e) {
+        }
+
+        try {
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyStr));
+            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+        } catch(Exception e) {
+//            logger.warn("解析私钥失败:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PRIKEY");
+        }
+        try {
+            byte[] decrypted = cipher.doFinal(encryptedMsgBuf);
+            return decrypted;
+        } catch (IllegalBlockSizeException e) {
+//            logger.error("解密失败,加密消息长度过长:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PARAM");
+        } catch (BadPaddingException e) {
+//            logger.error("解密失败,加密消息Padding不正确:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PARAM");
+        } catch (Exception e) {
+//            logger.error("解密失败,未知异常:{}", e.getMessage());
+            throw new RuntimeException("UNKNOWN_EXC");
+        }
+    }
+
+    public static byte[] sign(SignatureSuite suite, byte[] msgBuf, String privateKeyStr) {
+        Signature signature = null;
+        try {
+            signature = Signature.getInstance(suite.val());
+        } catch (Exception e) {
+        }
+        try {
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyStr));
+            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+            signature.initSign(privateKey);
+        } catch(Exception e) {
+//            logger.warn("解析私钥失败:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PRIKEY");
+        }
+        try {
+            signature.update(msgBuf);
+            return signature.sign();
+        } catch (SignatureException e) {
+            // 一般不会出现
+//            logger.error("签名失败,未知异常:{}", e.getMessage());
+            throw new RuntimeException("UNKNOWN_EXC");
+        }
+    }
+
+    public static boolean verifySign(SignatureSuite suite, byte[] msgBuf, byte[] sign, String publicKeyStr) {
+        Signature signature = null;
+        try {
+            signature = Signature.getInstance(suite.val());
+        } catch (Exception e) {
+        }
+
+        try {
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
+            PublicKey publicKey = keyFactory.generatePublic(keySpec);
+            signature.initVerify(publicKey);
+        } catch(Exception e) {
+//            logger.warn("解析公钥失败:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PUBKEY");
+        }
+        try {
+            signature.update(msgBuf);
+            return signature.verify(sign);
+        } catch (SignatureException e) {
+            e.printStackTrace();
+            // 一般不会出现
+//            logger.error("验签失败,错误的签名格式:{}", e.getMessage());
+            throw new RuntimeException("INVALID_PARAM");
+        }
+    }
+}

+ 144 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/RSAUtils.java

@@ -0,0 +1,144 @@
+package com.ruoyi.app.utils;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.*;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RSAUtils {
+    public static final String CHARSET = "UTF-8";
+    public static final String RSA_ALGORITHM = "RSA";
+
+
+    public static Map<String, String> createKeys(int keySize) {
+        //为RSA算法创建一个KeyPairGenerator对象
+        KeyPairGenerator kpg;
+        try {
+            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
+        }
+
+        //初始化KeyPairGenerator对象,密钥长度
+        kpg.initialize(keySize);
+        //生成密匙对
+        KeyPair keyPair = kpg.generateKeyPair();
+        //得到公钥
+        Key publicKey = keyPair.getPublic();
+        String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
+        //得到私钥
+        Key privateKey = keyPair.getPrivate();
+        String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
+        Map<String, String> keyPairMap = new HashMap<String, String>();
+        keyPairMap.put("publicKey", publicKeyStr);
+        keyPairMap.put("privateKey", privateKeyStr);
+
+        return keyPairMap;
+    }
+
+    /**
+     * 得到公钥
+     *
+     * @param publicKey 密钥字符串(经过base64编码)
+     * @throws Exception
+     */
+    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        //通过X509编码的Key指令获得公钥对象
+        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
+        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
+        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
+        return key;
+    }
+
+    /**
+     * 得到私钥
+     *
+     * @param privateKey 密钥字符串(经过base64编码)
+     * @throws Exception
+     */
+    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        //通过PKCS#8编码的Key指令获得私钥对象
+        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
+        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
+        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
+        return key;
+    }
+
+    public static byte[] encrypt(byte[] data, Key key) throws Exception {
+        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+        cipher.init(Cipher.ENCRYPT_MODE, key);
+        return rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data
+                , ((RSAKey) key).getModulus().bitLength());
+    }
+
+    public static byte[] decrypt(byte[] data, Key key) throws Exception {
+        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+        cipher.init(Cipher.DECRYPT_MODE, key);
+        return rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, data, ((RSAKey) key)
+                .getModulus()
+                .bitLength());
+    }
+
+    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
+        int maxBlock;
+        if (opmode == Cipher.DECRYPT_MODE) {
+            maxBlock = keySize / 8;
+        } else {
+            maxBlock = keySize / 8 - 11;
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+        byte[] buff;
+        int i = 0;
+        try {
+            while (datas.length > offSet) {
+                if (datas.length - offSet > maxBlock) {
+                    buff = cipher.doFinal(datas, offSet, maxBlock);
+                } else {
+                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
+                }
+                out.write(buff, 0, buff.length);
+                i++;
+                offSet = i * maxBlock;
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
+        }
+        byte[] resultDatas = out.toByteArray();
+        try {
+            out.close();
+        } catch (IOException e) {
+            throw new RuntimeException("关闭流失败", e);
+        }
+
+        return resultDatas;
+    }
+
+    public static String DoRSASha256(String input, RSAPrivateKey privateKey) throws Exception {
+//        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+//        messageDigest.update(input.getBytes(CHARSET));
+//        byte[] digested = messageDigest.digest();
+
+        Signature signature = Signature.getInstance("SHA256withRSA");
+        signature.initSign(privateKey);
+        signature.update(input.getBytes(CHARSET));
+        return Base64.encodeBase64String(signature.sign());
+    }
+
+    public static boolean VerifyRSASha256(String input, String sign, RSAPublicKey publicKey) throws Exception {
+        Signature signature = Signature.getInstance("SHA256withRSA");
+        signature.initVerify(publicKey);
+        signature.update(input.getBytes(CHARSET));
+        return signature.verify(Base64.decodeBase64(sign));
+    }
+}

+ 145 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/RsaMima.java

@@ -0,0 +1,145 @@
+package com.ruoyi.app.utils;
+
+import org.apache.commons.codec.binary.Base64;
+import javax.crypto.Cipher;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+public class RsaMima {
+    // Rsa 私钥
+    public static String privateKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY"
+            + "7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN"
+            + "PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA"
+            + "kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow"
+            + "cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv"
+            + "DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh"
+            + "YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3"
+            + "UP8iWi1Qw0Y=";
+
+    /**
+     * 私钥解密
+     *
+     * @param text 待解密的文本
+     * @return 解密后的文本
+     */
+    public  String decryptByPrivateKey(String text) throws Exception
+    {
+        return decryptByPrivateKey(privateKey, text);
+    }
+
+    /**
+     * 公钥解密
+     *
+     * @param publicKeyString 公钥
+     * @param text 待解密的信息
+     * @return 解密后的文本
+     */
+    public static String decryptByPublicKey(String publicKeyString, String text) throws Exception
+    {
+        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.DECRYPT_MODE, publicKey);
+        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
+        return new String(result);
+    }
+
+    /**
+     * 私钥加密
+     *
+     * @param privateKeyString 私钥
+     * @param text 待加密的信息
+     * @return 加密后的文本
+     */
+    public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception
+    {
+        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+        byte[] result = cipher.doFinal(text.getBytes());
+        return Base64.encodeBase64String(result);
+    }
+
+    /**
+     * 私钥解密
+     *
+     * @param privateKeyString 私钥
+     * @param text 待解密的文本
+     * @return 解密后的文本
+     */
+    public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception
+    {
+        PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.DECRYPT_MODE, privateKey);
+        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
+        return new String(result);
+    }
+
+    /**
+     * 公钥加密
+     *
+     * @param publicKeyString 公钥
+     * @param text 待加密的文本
+     * @return 加密后的文本
+     */
+    public static String encryptByPublicKey(String publicKeyString, String text) throws Exception
+    {
+        X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        byte[] result = cipher.doFinal(text.getBytes());
+        return Base64.encodeBase64String(result);
+    }
+
+    /**
+     * 构建RSA密钥对
+     *
+     * @return 生成后的公私钥信息
+     */
+    public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException
+    {
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(1024);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
+        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
+        String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
+        String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
+        return new RsaKeyPair(publicKeyString, privateKeyString);
+    }
+
+    /**
+     * RSA密钥对对象
+     */
+    public static class RsaKeyPair
+    {
+        private final String publicKey;
+        private final String privateKey;
+
+        public RsaKeyPair(String publicKey, String privateKey)
+        {
+            this.publicKey = publicKey;
+            this.privateKey = privateKey;
+        }
+
+        public String getPublicKey()
+        {
+            return publicKey;
+        }
+
+        public String getPrivateKey()
+        {
+            return privateKey;
+        }
+    }
+}

+ 138 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/SftSignUtil.java

@@ -0,0 +1,138 @@
+package com.ruoyi.app.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.SneakyThrows;
+import org.apache.commons.lang3.StringUtils;
+
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class SftSignUtil {
+    public final static Charset UTF_8 = Charset.forName("UTF-8");
+
+
+    @SneakyThrows
+    public static String VNSignData(Map<String, String> signDataMap) {
+        List fieldNames = new ArrayList(signDataMap.keySet());
+        Collections.sort(fieldNames);
+        StringBuilder hashData = new StringBuilder();
+        StringBuilder query = new StringBuilder();
+        Iterator itr = fieldNames.iterator();
+        while (itr.hasNext()) {
+            String fieldName = (String) itr.next();
+            String fieldValue = (String) signDataMap.get(fieldName);
+            if ((fieldValue != null) && (fieldValue.length() > 0)) {
+                //Build hash data
+                hashData.append(fieldName);
+                hashData.append('=');
+                hashData.append(fieldValue);
+                //Build query
+                query.append(URLEncoder.encode(fieldName,
+                        StandardCharsets.US_ASCII.toString()));
+                query.append('=');
+                query.append(URLEncoder.encode(fieldValue,
+                        StandardCharsets.US_ASCII.toString()));
+                if (itr.hasNext()) {
+                    query.append('&');
+                    hashData.append('&');
+                }
+            }
+        }
+        return hashData.toString();
+    }
+
+    public static String formatSignData(Map<String, String> signDataMap) {
+        Set<String> sortedSet = new TreeSet<String>(signDataMap.keySet());
+        StringBuffer sb = new StringBuffer();
+        for (String key : sortedSet) {
+            if ("sign".equalsIgnoreCase(key)) {
+                continue;
+            }
+
+            if (signDataMap.get(key) != null) {
+                String v = String.valueOf(signDataMap.get(key));
+                if (StringUtils.isNotBlank(v)) {
+                    sb.append(key);
+                    sb.append("=");
+                    sb.append(v);
+                    sb.append("&");
+                }
+            }
+        }
+        String s = sb.toString();
+        if (s.length() > 0) {
+            s = s.substring(0, s.length() - 1);
+        }
+//		log.debug("To be signed data: {}", s);
+        return s;
+    }
+
+    public static boolean verifySign(String signType, String signData, String sign, String authMchPublicKey) {
+        if ("md5".equals(signType.toLowerCase())) {
+            return md5VerifySign(signData, sign, authMchPublicKey);
+        } else {
+            try {
+                return rsaVerifySign(signData, sign, authMchPublicKey);
+            } catch (Exception e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return false;
+            }
+        }
+    }
+
+    public static boolean rsaVerifySign(String signData, String sign, String authMchPublicKey) throws Exception {
+        RSAPublicKey key = RSAUtils.getPublicKey(authMchPublicKey);
+        return RSAUtils.VerifyRSASha256( signData,sign, key);
+    }
+
+    public static boolean md5VerifySign(String signData, String sign, String authMchPublicKey) {
+        String lsign = md5Sign(signData, authMchPublicKey);
+        return lsign.equals(sign.toLowerCase());
+    }
+
+    public static String sign(String signType, String signData, String sftPrivateKey) throws Exception {
+        if ("md5".equals(signType.toLowerCase())) {
+            return md5Sign(signData, sftPrivateKey);
+        } else {
+
+            return rsaSign(signData, sftPrivateKey);
+        }
+    }
+
+    public static String rsaSign(String signData, String sftPrivateKey) throws Exception  {
+        RSAPrivateKey key = RSAUtils.getPrivateKey(sftPrivateKey);
+        return RSAUtils.DoRSASha256( signData, key);
+    }
+
+    public static String md5Sign(String signData, String sftPrivateKey) {
+        String sign = PayMD5.MD5Encode(signData + sftPrivateKey).toLowerCase();
+        return sign;
+    }
+
+    public static JSONObject sortJson(JSONObject signDataJson) {
+        @SuppressWarnings("unchecked")
+        Set<String> sortedSet = new TreeSet<String>(signDataJson.keySet());
+        JSONObject tmp = new JSONObject();
+        for (String key : sortedSet) {
+            if ("sign".equalsIgnoreCase(key)) {
+                continue;
+            }
+            tmp.put(key, signDataJson.get(key));
+        }
+        return tmp;
+    }
+
+
+    public static String signs(Map<String, String> signDataMap, String sftPrivateKey) {
+        String toBeSignedData = formatSignData(signDataMap);
+        byte[] signBuf = RSAUtil.sign(RSAUtil.SignatureSuite.SHA256, toBeSignedData.getBytes(UTF_8),
+                sftPrivateKey);
+        return new String(Base64.getEncoder().encode(signBuf), UTF_8);
+    }
+}

+ 159 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/StrKit.java

@@ -0,0 +1,159 @@
+package com.ruoyi.app.utils;
+
+public class StrKit {
+    /**
+     * 棣栧瓧姣嶅彉灏忓啓
+     */
+    public static String firstCharToLowerCase(String str) {
+        char firstChar = str.charAt(0);
+        if (firstChar >= 'A' && firstChar <= 'Z') {
+            char[] arr = str.toCharArray();
+            arr[0] += ('a' - 'A');
+            return new String(arr);
+        }
+        return str;
+    }
+
+    /**
+     * 棣栧瓧姣嶅彉澶у啓
+     */
+    public static String firstCharToUpperCase(String str) {
+        char firstChar = str.charAt(0);
+        if (firstChar >= 'a' && firstChar <= 'z') {
+            char[] arr = str.toCharArray();
+            arr[0] -= ('a' - 'A');
+            return new String(arr);
+        }
+        return str;
+    }
+
+    /**
+     * 瀛楃涓蹭负 null 鎴栬�呭唴閮ㄥ瓧绗﹀叏閮ㄤ负 ' ' '\t' '\n' '\r' 杩欏洓绫诲瓧绗︽椂杩斿洖 true
+     */
+    public static boolean isBlank(String str) {
+        if (str == null) {
+            return true;
+        }
+        int len = str.length();
+        if (len == 0) {
+            return true;
+        }
+        for (int i = 0; i < len; i++) {
+            switch (str.charAt(i)) {
+                case ' ':
+                case '\t':
+                case '\n':
+                case '\r':
+                    // case '\b':
+                    // case '\f':
+                    break;
+                default:
+                    return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean notBlank(String str) {
+        return !isBlank(str);
+    }
+
+    public static boolean notBlank(String... strings) {
+        if (strings == null || strings.length == 0) {
+            return false;
+        }
+        for (String str : strings) {
+            if (isBlank(str)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean notNull(Object... paras) {
+        if (paras == null) {
+            return false;
+        }
+        for (Object obj : paras) {
+            if (obj == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static String toCamelCase(String stringWithUnderline) {
+        if (stringWithUnderline.indexOf('_') == -1) {
+            return stringWithUnderline;
+        }
+
+        stringWithUnderline = stringWithUnderline.toLowerCase();
+        char[] fromArray = stringWithUnderline.toCharArray();
+        char[] toArray = new char[fromArray.length];
+        int j = 0;
+        for (int i = 0; i < fromArray.length; i++) {
+            if (fromArray[i] == '_') {
+                // 褰撳墠瀛楃涓轰笅鍒掔嚎鏃讹紝灏嗘寚閽堝悗绉讳竴浣嶏紝灏嗙揣闅忎笅鍒掔嚎鍚庨潰涓�涓瓧绗﹁浆鎴愬ぇ鍐欏苟瀛樻斁
+                i++;
+                if (i < fromArray.length) {
+                    toArray[j++] = Character.toUpperCase(fromArray[i]);
+                }
+            } else {
+                toArray[j++] = fromArray[i];
+            }
+        }
+        return new String(toArray, 0, j);
+    }
+
+    public static String join(String[] stringArray) {
+        StringBuilder sb = new StringBuilder();
+        for (String s : stringArray) {
+            sb.append(s);
+        }
+        return sb.toString();
+    }
+
+    public static String join(String[] stringArray, String separator) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < stringArray.length; i++) {
+            if (i > 0) {
+                sb.append(separator);
+            }
+            sb.append(stringArray[i]);
+        }
+        return sb.toString();
+    }
+
+    public static boolean equals(String a, String b) {
+        return a == null ? b == null : a.equals(b);
+    }
+
+    public static String getRandomUUID() {
+        return java.util.UUID.randomUUID().toString().replace("-", "");
+    }
+
+
+    /**
+     * 字符串转换为16进制字符串
+     *
+     * @param s
+     * @return
+     */
+    public static String stringToHexString(String s) {
+        String str = "";
+        for (int i = 0; i < s.length(); i++) {
+            int ch = s.charAt(i);
+            String s4 = Integer.toHexString(ch);
+            str = str + s4;
+        }
+        return str;
+    }
+    public static String cnToUnicode(String cn) {
+        char[] chars = cn.toCharArray();
+        String returnStr = "";
+        for (int i = 0; i < chars.length; i++) {
+            returnStr += "\\u" + Integer.toString(chars[i], 16);
+        }
+        return returnStr;
+    }
+}

+ 241 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/SysFileInfoController.java

@@ -0,0 +1,241 @@
+package com.ruoyi.app.utils;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.framework.web.domain.server.Sys;
+import com.ruoyi.system.domain.PosFreight;
+import com.ruoyi.system.domain.UserFootprint;
+import com.ruoyi.system.mapper.PosFreightMapper;
+import com.ruoyi.system.service.IPosFreightService;
+import com.ruoyi.system.utils.AddPush;
+import com.ruoyi.system.utils.GetArea;
+import com.ruoyi.web.controller.common.CommonController;
+import io.swagger.models.auth.In;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import redis.clients.jedis.Jedis;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.Calendar;
+import java.util.List;
+
+@RestController
+@RequestMapping("/utils")
+public class SysFileInfoController extends BaseController {
+    @Autowired
+    private IPosFreightService posFreightService;
+    @Autowired
+    private PosFreightMapper posFreightMapper;
+    private static final Logger log = LoggerFactory.getLogger(SysFileInfoController.class);
+
+    //上传
+    @Anonymous
+    @PostMapping("/Upload")
+    @ResponseBody
+    public AjaxResult addSave(@RequestParam("file") MultipartFile file) throws IOException {
+        // 上传文件路径
+        String filePath = RuoYiConfig.getUploadPath();
+        // 上传并返回新文件名称
+        String fileName = FileUploadUtils.upload(filePath, file);
+        return success(MessageUtils.message("no.upload.success"), fileName);
+    }
+
+    //返回附近地址
+    @Anonymous
+    @GetMapping("/getLocationAddr")
+    public AjaxResult getLocationAddr(@RequestParam String latlng,
+                                      @RequestParam Integer type,
+                                      @RequestParam(defaultValue = "") String id) {
+        Jedis jedis = new Jedis("localhost", 6379);
+        GetArea area = new GetArea();
+        String lang = jedis.get(id) == null ? "vi" : jedis.get(id);
+        JSONObject reg;
+        if (type == 0) {
+            reg = area.getarearess(latlng, lang);
+        } else {
+            reg = area.getgoogle(latlng, lang);
+        }
+        return success(reg);
+    }
+
+    //地址逆向
+    @Anonymous
+    @GetMapping("/getAddr")
+    public AjaxResult getAddr(@RequestParam String latlng,
+                              @RequestParam(defaultValue = "") String id) {
+        Jedis jedis = new Jedis("localhost", 6379);
+        String lang = jedis.get(id) == null ? "vi" : jedis.get(id);
+        GetArea area = new GetArea();
+        JSONObject reg = area.getgoogleadd(latlng, lang);
+        return success(reg);
+    }
+
+    //坐标转换
+    @Anonymous
+    @GetMapping("/setLocat")
+    public AjaxResult setLocat(@RequestParam String latlng,
+                               @RequestParam Integer from,
+                               @RequestParam Integer to) {
+        GetArea area = new GetArea();
+        JSONObject reg = area.setlatlng(latlng, from, to);
+        return success(reg);
+    }
+
+    //坐标转换
+    @Anonymous
+    @GetMapping("/GCJ2TOWGS")
+    public AjaxResult GCJ2TOWGS(@RequestParam Double lng,
+                                @RequestParam Double lat) {
+        GetArea area = new GetArea();
+        String reg = area.convertGCJ2WGS(lng, lat);
+        return success(MessageUtils.message("no.convert.success"), reg);
+    }
+
+    //获取短信
+    @Anonymous
+    @GetMapping("/addpush")
+    public AjaxResult addpush(@RequestParam String cid, @RequestParam String title, @RequestParam String content) {
+        AddPush push = new AddPush();
+        Boolean reg = push.gopush(cid, title, content);
+        if (reg) {
+            return success(MessageUtils.message("no.send.success"));
+        } else {
+            return error(MessageUtils.message("no.send.fail"));
+        }
+    }
+
+    //计算运费----直线
+    @Anonymous
+    @GetMapping("/getyunfei")
+    public AjaxResult getyunfei(@RequestParam double lat1,
+                                @RequestParam double lng1,
+                                @RequestParam double lat2,
+                                @RequestParam double lng2) {
+        List<PosFreight> freights = posFreightMapper.getyunjia();
+        Long yunjia;
+        Long qyjvli;
+        Long qyjiage;
+        if (freights.size() == 0) {
+            List<PosFreight> hts = posFreightMapper.getmiuyunjia();
+            yunjia = hts.get(0).getFreight() / hts.get(0).getDistance();
+            qyjvli = hts.get(0).getStartingDistance();
+            qyjiage = hts.get(0).getStartingFare();
+        } else {
+            yunjia = freights.get(0).getFreight() / freights.get(0).getDistance();
+            qyjvli = freights.get(0).getStartingDistance();
+            qyjiage = freights.get(0).getStartingFare();
+        }
+        GetJvli jvli = new GetJvli();
+        Double psjvli = jvli.getDistance(lat1, lng1, lat2, lng2);
+        DecimalFormat df = new DecimalFormat("#");
+        DecimalFormat jl = new DecimalFormat("#.0");
+        Double jsjl = psjvli <= qyjvli ? 0 : psjvli - qyjvli;
+        System.out.println("==========" + jsjl);
+        String yunf = df.format(yunjia * (jsjl < 0.5 ? 0 : jsjl >= 0.5 && jsjl < 1 ? 1 : jsjl));
+        Long sjyunf = Long.parseLong(yunf) + qyjiage;
+        BigDecimal bb = BigDecimal.valueOf(sjyunf);
+        BigDecimal Res = sjyunf < 1000 ? bb : bb.setScale(-3, BigDecimal.ROUND_HALF_UP);
+        JSONObject org = new JSONObject();
+        org.put("jvli", Double.valueOf(jl.format(psjvli)));
+        org.put("freight", Res);
+        org.put("yunf", sjyunf);
+        return success(MessageUtils.message("no.obtained.permission"), org);
+    }
+
+    //计算运费
+    @Anonymous
+    @GetMapping("/getZuiyyfei")
+    public AjaxResult getZuiyyfei(@RequestParam String quli) {
+        List<PosFreight> freights = posFreightMapper.getyunjia();
+        Long yunjia;
+        Long qyjvli;
+        Long qyjiage;
+        if (freights.size() == 0) {
+            List<PosFreight> hts = posFreightMapper.getmiuyunjia();
+            yunjia = hts.get(0).getFreight() / hts.get(0).getDistance();
+            qyjvli = hts.get(0).getStartingDistance();
+            qyjiage = hts.get(0).getStartingFare();
+        } else {
+            yunjia = freights.get(0).getFreight() / freights.get(0).getDistance();
+            qyjvli = freights.get(0).getStartingDistance();
+            qyjiage = freights.get(0).getStartingFare();
+        }
+        Double psjvli = Double.valueOf(quli);
+        DecimalFormat df = new DecimalFormat("#");
+        DecimalFormat jl = new DecimalFormat("#.0");
+        Double jsjl = psjvli <= qyjvli ? 0 : psjvli - qyjvli;
+        System.out.println("==========" + jsjl);
+        String yunf = df.format(yunjia * (jsjl < 0.5 ? 0 : jsjl >= 0.5 && jsjl < 1 ? 1 : jsjl));
+        Long sjyunf = Long.parseLong(yunf) + qyjiage;
+        BigDecimal bb = BigDecimal.valueOf(sjyunf);
+        BigDecimal Res = sjyunf < 1000 ? bb : bb.setScale(-3, BigDecimal.ROUND_HALF_UP);
+        JSONObject org = new JSONObject();
+        org.put("jvli", Double.valueOf(jl.format(psjvli)));
+        org.put("freight", Res);
+        org.put("yunf", sjyunf);
+        return success(MessageUtils.message("no.obtained.permission"), org);
+    }
+
+    //计算导航路径
+    @Anonymous
+    @GetMapping("/getluxianjvli")
+    public AjaxResult getluxianjvli(@RequestParam String latlng1,
+                                    @RequestParam String latlng2,
+                                    @RequestParam(defaultValue = "") String id) {
+        log.info("谷歌地图:开始处理路径计算请求 -> ID: {}, 坐标1: {}, 坐标2: {}", id, latlng1, latlng2);
+        try(Jedis jedis=new Jedis("localhost", 6379);) {
+            //Jedis jedis = new Jedis("localhost", 6379);
+            String lang = jedis.get(id) == null ? "vi" : jedis.get(id);
+            GetArea area = new GetArea();
+            JSONObject reg = area.getluxian(latlng1, latlng2, lang);
+            log.info("谷歌地图:返回---" + reg.toString());
+            return success(reg.getJSONArray("routes"));
+        } catch (Exception e) {
+            // 异常捕获
+            log.error("谷歌地图:处理路径计算请求异常 -> ID: {}, 错误信息: {}", id, e.getMessage(), e);
+            return error(MessageUtils.message("no.map.exception"));
+        }
+
+    }
+
+    /**
+     * Mapbox 计算导航路径
+     * @param lnglat1
+     * @param lnglat2
+     * @param id
+     * @return
+     */
+    @Anonymous
+    @GetMapping("/getluxianjvliMp")
+    public AjaxResult getluxianjvliMp(@RequestParam String lnglat1,
+                                    @RequestParam String lnglat2,
+                                    @RequestParam(defaultValue = "") String id) {
+        log.info("Mapbox地图:开始处理路径计算请求 -> ID: {}, 坐标1: {}, 坐标2: {}", id, lnglat1, lnglat2);
+        try(Jedis jedis=new Jedis("localhost", 6379);) {
+            //Jedis jedis = new Jedis("localhost", 6379);
+            String lang = jedis.get(id) == null ? "vi" : jedis.get(id);
+            GetArea area = new GetArea();
+            JSONObject reg = area.getmpluxian(lnglat1, lnglat2);
+            log.info("Mapbox地图:返回---" + reg.toString());
+            return success(reg.getJSONArray("routes"));
+        } catch (Exception e) {
+            // 异常捕获
+            log.error("Mapbox地图:处理路径计算请求异常 -> ID: {}, 错误信息: {}", id, e.getMessage(), e);
+            return error(MessageUtils.message("no.map.exception"));
+        }
+
+    }
+}

+ 85 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/UUIDUtil.java

@@ -0,0 +1,85 @@
+package com.ruoyi.app.utils;
+
+import java.util.UUID;
+
+public class UUIDUtil {
+
+    /**
+     * 获得4个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get4UUID() {
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[1];
+    }
+
+    /**
+     * 获得8个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get8UUID() {
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[0];
+    }
+
+    /**
+     * 获得12个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get12UUID() {
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[0] + idd[1];
+    }
+
+    /**
+     * 获得16个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get16UUID() {
+
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[0] + idd[1] + idd[2];
+    }
+
+    /**
+     * 获得20个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get20UUID() {
+
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[0] + idd[1] + idd[2] + idd[3];
+    }
+
+    /**
+     * 获得24个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get24UUID() {
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[0] + idd[1] + idd[4];
+    }
+
+    /**
+     * 获得32个长度的十六进制的UUID
+     *
+     * @return UUID
+     */
+    public String get32UUID() {
+        UUID id = UUID.randomUUID();
+        String[] idd = id.toString().split("-");
+        return idd[0] + idd[1] + idd[2] + idd[3] + idd[4];
+    }
+}

+ 132 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/VNPay.java

@@ -0,0 +1,132 @@
+package com.ruoyi.app.utils;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * @author CTT VNPAY
+ */
+public class VNPay {
+
+    public static String vnp_PayUrl = "https://sandbox.vnpayment.vn/paymentv2/vpcpay.html";
+    public static String vnp_ReturnUrl = "https://api.cityexpress168.com.vn/pay/payJson";
+    public static String vnp_TmnCode = "CITYTTTT";
+    public static String secretKey = "FHWEXJGPRITXYMSELLSOYTOGWXPRMMSS";
+    public static String vnp_ApiUrl = "https://sandbox.vnpayment.vn/merchant_webapi/api/transaction";
+
+    public static String md5(String message) {
+        String digest = null;
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            byte[] hash = md.digest(message.getBytes("UTF-8"));
+            StringBuilder sb = new StringBuilder(2 * hash.length);
+            for (byte b : hash) {
+                sb.append(String.format("%02x", b & 0xff));
+            }
+            digest = sb.toString();
+        } catch (UnsupportedEncodingException ex) {
+            digest = "";
+        } catch (NoSuchAlgorithmException ex) {
+            digest = "";
+        }
+        return digest;
+    }
+
+    public static String Sha256(String message) {
+        String digest = null;
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-256");
+            byte[] hash = md.digest(message.getBytes("UTF-8"));
+            StringBuilder sb = new StringBuilder(2 * hash.length);
+            for (byte b : hash) {
+                sb.append(String.format("%02x", b & 0xff));
+            }
+            digest = sb.toString();
+        } catch (UnsupportedEncodingException ex) {
+            digest = "";
+        } catch (NoSuchAlgorithmException ex) {
+            digest = "";
+        }
+        return digest;
+    }
+
+    //Util for VNPAY
+    public static String hashAllFields(Map fields) {
+        List fieldNames = new ArrayList(fields.keySet());
+        Collections.sort(fieldNames);
+        StringBuilder sb = new StringBuilder();
+        Iterator itr = fieldNames.iterator();
+        while (itr.hasNext()) {
+            String fieldName = (String) itr.next();
+            String fieldValue = (String) fields.get(fieldName);
+            if ((fieldValue != null) && (fieldValue.length() > 0)) {
+                sb.append(fieldName);
+                sb.append("=");
+                sb.append(fieldValue);
+            }
+            if (itr.hasNext()) {
+                sb.append("&");
+            }
+        }
+        System.out.println("sb:"+sb.toString());
+        return hmacSHA512(secretKey,sb.toString());
+    }
+
+    public static String hmacSHA512(final String key, final String data) {
+        try {
+
+            if (key == null || data == null) {
+                throw new NullPointerException();
+            }
+            final Mac hmac512 = Mac.getInstance("HmacSHA512");
+            byte[] hmacKeyBytes = key.getBytes();
+            final SecretKeySpec secretKey = new SecretKeySpec(hmacKeyBytes, "HmacSHA512");
+            hmac512.init(secretKey);
+            byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
+            byte[] result = hmac512.doFinal(dataBytes);
+            StringBuilder sb = new StringBuilder(2 * result.length);
+            for (byte b : result) {
+                sb.append(String.format("%02x", b & 0xff));
+            }
+            return sb.toString();
+
+        } catch (Exception ex) {
+            return "";
+        }
+    }
+
+    public static String getIpAddress(HttpServletRequest request) {
+        String ipAdress;
+        try {
+            ipAdress = request.getHeader("X-FORWARDED-FOR");
+            if (ipAdress == null) {
+                ipAdress = request.getRemoteAddr();
+            }
+        } catch (Exception e) {
+            ipAdress = "Invalid IP:" + e.getMessage();
+        }
+        return ipAdress;
+    }
+
+    public static String getRandomNumber(int len) {
+        Random rnd = new Random();
+        String chars = "0123456789";
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            sb.append(chars.charAt(rnd.nextInt(chars.length())));
+        }
+        return sb.toString();
+    }
+}
+

+ 24 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/event/PushEvent.java

@@ -0,0 +1,24 @@
+package com.ruoyi.app.utils.event;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * 推送事件
+ */
+@Getter
+@Setter
+public class PushEvent extends ApplicationEvent {
+    private Long userId;
+    private String title;
+    private String content;
+    private String body;
+    public PushEvent(Long userId, String title, String content, String body) {
+        super(new Object());
+        this.userId = userId;
+        this.title = title;
+        this.content = content;
+        this.body = body;
+    }
+}

+ 29 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/event/PushEventListener.java

@@ -0,0 +1,29 @@
+package com.ruoyi.app.utils.event;
+
+
+import com.ruoyi.system.domain.PushMessage;
+import com.ruoyi.system.service.IPushMessageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PushEventListener  implements ApplicationListener<PushEvent> {
+
+    @Autowired
+    private IPushMessageService pushMessageService;
+
+    @Override
+    @Async(value = "threadPoolTaskExecutor")
+    public void onApplicationEvent(PushEvent event) {
+        PushMessage pushMessage = new PushMessage();
+        pushMessage.setTitle(event.getTitle());
+        pushMessage.setContent(event.getContent());
+        pushMessage.setBody(event.getBody());
+        pushMessage.setUserId(event.getUserId());
+        pushMessage.setTime(new java.util.Date());
+        pushMessageService.insertPushMessage(pushMessage);
+
+    }
+}

+ 28 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/event/PushEventService.java

@@ -0,0 +1,28 @@
+package com.ruoyi.app.utils.event;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PushEventService {
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+    /**
+     * 发送事件
+     * @param userId
+     * @param title
+     * @param content
+     * @param body
+     */
+    @Async(value = "threadPoolTaskExecutor")
+    public void PublisherEvent(
+            Long userId,
+            String title,
+            String content,
+            String body) {
+        PushEvent event = new PushEvent(userId, title, content, body);
+        eventPublisher.publishEvent(event);
+    }
+}

+ 24 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/trtc/Base64URL.java

@@ -0,0 +1,24 @@
+package com.ruoyi.app.utils.trtc;
+
+import java.util.Base64;
+
+public class Base64URL {
+    public static byte[] base64EncodeUrl(byte[] input) {
+        byte[] base64 = Base64.getEncoder().encode(input);
+        for (int i = 0; i < base64.length; ++i)
+            switch (base64[i]) {
+                case '+':
+                    base64[i] = '*';
+                    break;
+                case '/':
+                    base64[i] = '-';
+                    break;
+                case '=':
+                    base64[i] = '_';
+                    break;
+                default:
+                    break;
+            }
+        return base64;
+    }
+}

+ 318 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/trtc/TLSSigAPIv2.java

@@ -0,0 +1,318 @@
+package com.ruoyi.app.utils.trtc;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.security.*;
+
+import java.util.Arrays;
+import java.util.zip.Deflater;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.json.JSONObject;
+
+public class TLSSigAPIv2 {
+    private long sdkappid = 1600036174;
+    private String key = "e3b6abb54f40fc92d207ab95616887b1f06ffaf97e60fcb1f780e7002a3c114e";
+
+    public TLSSigAPIv2(long sdkappid, String key) {
+        this.sdkappid = sdkappid;
+        this.key = key;
+    }
+
+    public TLSSigAPIv2() {
+
+    }
+
+    /**
+     * 【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据
+     * <p>
+     * 【参数说明】
+     *
+     * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
+     * @param expire - UserSig 票据的过期时间,单位是秒,比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了。
+     * @return usersig -生成的签名
+     */
+
+    /**
+     * Function: Used to issue UserSig that is required by the TRTC and IM services.
+     * <p>
+     * Parameter description:
+     *
+     * @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
+     * @param expire - UserSig expiration time, in seconds. For example, 86400 indicates that the generated UserSig will expire one day after being generated.
+     * @return usersig - Generated signature.
+     */
+    public String genUserSig(String userid, long expire) {
+        return genUserSig(userid, expire, null);
+    }
+
+    /**
+     * 【功能说明】
+     * 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。
+     * PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力:
+     * - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。
+     * - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。
+     * 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】/【应用管理】/【应用信息】中打开“启动权限密钥”开关。
+     * <p>
+     * 【参数说明】
+     *
+     * @param userid       - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
+     * @param expire       - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。
+     * @param roomid       - 房间号,用于指定该 userid 可以进入的房间号
+     * @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关:
+     *                     - 第 1 位:0000 0001 = 1,创建房间的权限
+     *                     - 第 2 位:0000 0010 = 2,加入房间的权限
+     *                     - 第 3 位:0000 0100 = 4,发送语音的权限
+     *                     - 第 4 位:0000 1000 = 8,接收语音的权限
+     *                     - 第 5 位:0001 0000 = 16,发送视频的权限
+     *                     - 第 6 位:0010 0000 = 32,接收视频的权限
+     *                     - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限
+     *                     - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限
+     *                     - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。
+     *                     - privilegeMap == 0010 1010 == 42  代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。
+     * @return usersig - 生成带userbuf的签名
+     */
+
+    /**
+     * Function:
+     * Used to issue PrivateMapKey that is optional for room entry.
+     * PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities.
+     *  - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room.
+     *  - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room.
+     * To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info.
+     *
+     * Parameter description:
+     *
+     * @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
+     * @param roomid - ID of the room to which the specified UserID can enter.
+     * @param expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated.
+     * @param privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features:
+     *  - Bit 1: 0000 0001 = 1, permission for room creation
+     *  - Bit 2: 0000 0010 = 2, permission for room entry
+     *  - Bit 3: 0000 0100 = 4, permission for audio sending
+     *  - Bit 4: 0000 1000 = 8, permission for audio receiving
+     *  - Bit 5: 0001 0000 = 16, permission for video sending
+     *  - Bit 6: 0010 0000 = 32, permission for video receiving
+     *  - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing)
+     *  - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing)
+     *  - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid.
+     *  - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data.
+     * @return usersig - Generate signature with userbuf
+     */
+    public String genPrivateMapKey(String userid, long expire, long roomid, long privilegeMap) {
+        byte[] userbuf = genUserBuf(userid, roomid, expire, privilegeMap, 0, "");  //生成userbuf
+        return genUserSig(userid, expire, userbuf);
+    }
+
+    /**
+     * 【功能说明】
+     * 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。
+     * PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力:
+     * - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。
+     * - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。
+     * 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】/【应用管理】/【应用信息】中打开“启动权限密钥”开关。
+     * <p>
+     * 【参数说明】
+     *
+     * @param userid       - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
+     * @param expire       - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。
+     * @param roomstr      - 字符串房间号,用于指定该 userid 可以进入的房间号
+     * @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关:
+     *                     - 第 1 位:0000 0001 = 1,创建房间的权限
+     *                     - 第 2 位:0000 0010 = 2,加入房间的权限
+     *                     - 第 3 位:0000 0100 = 4,发送语音的权限
+     *                     - 第 4 位:0000 1000 = 8,接收语音的权限
+     *                     - 第 5 位:0001 0000 = 16,发送视频的权限
+     *                     - 第 6 位:0010 0000 = 32,接收视频的权限
+     *                     - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限
+     *                     - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限
+     *                     - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。
+     *                     - privilegeMap == 0010 1010 == 42  代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。
+     * @return usersig - 生成带userbuf的签名
+     */
+
+    /**
+     * Function:
+     * Used to issue PrivateMapKey that is optional for room entry.
+     * PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities.
+     *  - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room.
+     *  - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room.
+     * To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info.
+     *
+     * Parameter description:
+     *
+     *
+     * @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
+     * @param roomid - ID of the room to which the specified UserID can enter.
+     * @param expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated.
+     * @param privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features:
+     *  - Bit 1: 0000 0001 = 1, permission for room creation
+     *  - Bit 2: 0000 0010 = 2, permission for room entry
+     *  - Bit 3: 0000 0100 = 4, permission for audio sending
+     *  - Bit 4: 0000 1000 = 8, permission for audio receiving
+     *  - Bit 5: 0001 0000 = 16, permission for video sending
+     *  - Bit 6: 0010 0000 = 32, permission for video receiving
+     *  - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing)
+     *  - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing)
+     *  - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid.
+     *  - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data.
+     * @return usersig - Generate signature with userbuf
+     */
+    public String genPrivateMapKeyWithStringRoomID(String userid, long expire, String roomstr, long privilegeMap) {
+        byte[] userbuf = genUserBuf(userid, 0, expire, privilegeMap, 0, roomstr);  //生成userbuf
+        return genUserSig(userid, expire, userbuf);
+    }
+
+    private String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
+        String contentToBeSigned = "TLS.identifier:" + identifier + "\n"
+                + "TLS.sdkappid:" + sdkappid + "\n"
+                + "TLS.time:" + currTime + "\n"
+                + "TLS.expire:" + expire + "\n";
+        if (null != base64Userbuf) {
+            contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
+        }
+        try {
+            byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
+            Mac hmac = Mac.getInstance("HmacSHA256");
+            SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
+            hmac.init(keySpec);
+            byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
+            return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
+        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+            return "";
+        }
+    }
+
+    private String genUserSig(String userid, long expire, byte[] userbuf) {
+
+        long currTime = System.currentTimeMillis() / 1000;
+
+        JSONObject sigDoc = new JSONObject();
+        sigDoc.put("TLS.ver", "2.0");
+        sigDoc.put("TLS.identifier", userid);
+        sigDoc.put("TLS.sdkappid", sdkappid);
+        sigDoc.put("TLS.expire", expire);
+        sigDoc.put("TLS.time", currTime);
+
+        String base64UserBuf = null;
+        if (null != userbuf) {
+            base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
+            sigDoc.put("TLS.userbuf", base64UserBuf);
+        }
+        String sig = hmacsha256(userid, currTime, expire, base64UserBuf);
+        if (sig.length() == 0) {
+            return "";
+        }
+        sigDoc.put("TLS.sig", sig);
+        Deflater compressor = new Deflater();
+        compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
+        compressor.finish();
+        byte[] compressedBytes = new byte[2048];
+        int compressedBytesLength = compressor.deflate(compressedBytes);
+        compressor.end();
+        return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
+                0, compressedBytesLength)))).replaceAll("\\s*", "");
+    }
+
+    public byte[] genUserBuf(String account, long dwAuthID, long dwExpTime,
+                             long dwPrivilegeMap, long dwAccountType, String RoomStr) {
+        //视频校验位需要用到的字段,按照网络字节序放入buf中
+        /*
+         cVer    unsigned char/1 版本号,填0
+         wAccountLen unsigned short /2   第三方自己的帐号长度
+         account wAccountLen 第三方自己的帐号字符
+         dwSdkAppid  unsigned int/4  sdkappid
+         dwAuthID    unsigned int/4  群组号码
+         dwExpTime   unsigned int/4  过期时间 ,直接使用填入的值
+         dwPrivilegeMap  unsigned int/4  权限位,主播0xff,观众0xab
+         dwAccountType   unsigned int/4  第三方帐号类型
+         */
+
+        //The fields required for the video check digit are placed in buf according to the network byte order.
+        /*
+         cVer    unsigned char/1 Version number, fill in 0
+         wAccountLen unsigned short /2   Third party's own account length
+         account wAccountLen Third party's own account characters
+         dwSdkAppid  unsigned int/4  sdkappid
+         dwAuthID    unsigned int/4  group number
+         dwExpTime   unsigned int/4  Expiration time , use the filled value directly
+         dwPrivilegeMap  unsigned int/4  Permission bits, host 0xff, audience 0xab
+         dwAccountType   unsigned int/4  Third-party account type
+        */
+        int accountLength = account.length();
+        int roomStrLength = RoomStr.length();
+        int offset = 0;
+        int bufLength = 1 + 2 + accountLength + 20 ;
+        if (roomStrLength > 0) {
+            bufLength = bufLength + 2 + roomStrLength;
+        }
+        byte[] userbuf = new byte[bufLength];
+
+        //cVer
+        if (roomStrLength > 0) {
+            userbuf[offset++] = 1;
+        } else {
+            userbuf[offset++] = 0;
+        }
+
+        //wAccountLen
+        userbuf[offset++] = (byte) ((accountLength & 0xFF00) >> 8);
+        userbuf[offset++] = (byte) (accountLength & 0x00FF);
+
+        //account
+        for (; offset < 3 + accountLength; ++offset) {
+            userbuf[offset] = (byte) account.charAt(offset - 3);
+        }
+
+        //dwSdkAppid
+        userbuf[offset++] = (byte) ((sdkappid & 0xFF000000) >> 24);
+        userbuf[offset++] = (byte) ((sdkappid & 0x00FF0000) >> 16);
+        userbuf[offset++] = (byte) ((sdkappid & 0x0000FF00) >> 8);
+        userbuf[offset++] = (byte) (sdkappid & 0x000000FF);
+
+        //dwAuthId,房间号
+        //dwAuthId, room number
+        userbuf[offset++] = (byte) ((dwAuthID & 0xFF000000) >> 24);
+        userbuf[offset++] = (byte) ((dwAuthID & 0x00FF0000) >> 16);
+        userbuf[offset++] = (byte) ((dwAuthID & 0x0000FF00) >> 8);
+        userbuf[offset++] = (byte) (dwAuthID & 0x000000FF);
+
+        //expire,过期时间,当前时间 + 有效期(单位:秒)
+        //expire,Expiration time, current time + validity period (unit: seconds)
+        long currTime = System.currentTimeMillis() / 1000;
+        long expire = currTime + dwExpTime;
+        userbuf[offset++] = (byte) ((expire & 0xFF000000) >> 24);
+        userbuf[offset++] = (byte) ((expire & 0x00FF0000) >> 16);
+        userbuf[offset++] = (byte) ((expire & 0x0000FF00) >> 8);
+        userbuf[offset++] = (byte) (expire & 0x000000FF);
+
+        //dwPrivilegeMap,权限位
+        //dwPrivilegeMap,Permission bits
+        userbuf[offset++] = (byte) ((dwPrivilegeMap & 0xFF000000) >> 24);
+        userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x00FF0000) >> 16);
+        userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x0000FF00) >> 8);
+        userbuf[offset++] = (byte) (dwPrivilegeMap & 0x000000FF);
+
+        //dwAccountType,账户类型
+        //dwAccountType,account type
+        userbuf[offset++] = (byte) ((dwAccountType & 0xFF000000) >> 24);
+        userbuf[offset++] = (byte) ((dwAccountType & 0x00FF0000) >> 16);
+        userbuf[offset++] = (byte) ((dwAccountType & 0x0000FF00) >> 8);
+        userbuf[offset++] = (byte) (dwAccountType & 0x000000FF);
+
+
+        if (roomStrLength > 0) {
+            //roomStrLen
+            userbuf[offset++] = (byte) ((roomStrLength & 0xFF00) >> 8);
+            userbuf[offset++] = (byte) (roomStrLength & 0x00FF);
+
+            //roomStr
+            for (; offset < bufLength; ++offset) {
+                userbuf[offset] = (byte) RoomStr.charAt(offset - (bufLength - roomStrLength));
+            }
+        }
+        return userbuf;
+    }
+}

+ 250 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/zaloPay/ZaloPay.java

@@ -0,0 +1,250 @@
+package com.ruoyi.app.utils.zaloPay;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.app.utils.zaloPayCrypto.HMACUtil;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+/**
+ * ZaloPay 工具类
+ *
+ * @author ruoyi
+ **/
+@Component
+public class ZaloPay {
+    @Autowired
+    private ZaloPayApiProperties apiProperties;
+
+    /**
+     * 生成 HMAC SHA256 签名
+     */
+
+    public static String getCurrentTimeString(String format) {
+        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT+7"));
+        SimpleDateFormat fmt = new SimpleDateFormat(format);
+        fmt.setCalendar(cal);
+        return fmt.format(cal.getTimeInMillis());
+    }
+
+    /**
+     * 创建ZaloPay订单,返回支付链接
+     *
+     * @param userId      用户唯一标识
+     * @param orderId     订单号(建议格式:yymmdd_唯一编号)
+     * @param amount      金额(单位:VND)
+     * @param description 订单描述
+     * @return ZaloPayCreateOrderResponse 支付响应数据
+     */
+    public  ZaloPayCreateOrderResponse createOrder(String userId, String orderId, long amount, String description,ZaloPayProperties.ZaloPayConfig config) throws Exception {
+//        ZaloPayConfig config = ZaloPayConfig.getZaloPayConfig(payType);
+        String APP_ID = config.getApp_id();
+        String KEY1 = config.getKey1();
+
+        System.out.println("进入zalopay CreateOrder orderId: " + orderId+" amount: " + amount);
+        // 从传入参数构建 embed_data
+        final Map<String, Object> embed_data = new HashMap<>();
+        // 如果有实际需要,可以在这里添加字段
+
+        // 从传入参数构建 item 列表
+        final List<Map<String, Object>> items = new ArrayList<>();
+        // 示例:添加一个商品项
+        Map<String, Object> item = new HashMap<>();
+
+//        item.put("item_price", amount / 100); // 假设金额以分为单位
+//        items.add(item);
+
+        String appTransId =getCurrentTimeString("yyMMdd") + "_" + orderId;
+        Map<String, Object> order = new HashMap<String, Object>(){{
+            put("app_id", APP_ID);
+            put("app_trans_id", appTransId);
+            put("app_time", System.currentTimeMillis()); //毫米级时间戳,时间戳与时区无关 miliseconds
+            put("app_user", userId);
+            put("amount", amount);
+            put("description", description);
+            //钱包支付
+            if(config.getPay_type().equals("3")){
+                put("bank_code", "zalopayapp");
+                put("embed_data", "{}");
+            }
+            //银行卡支付
+            if(config.getPay_type().equals("5")){
+                put("bank_code", "");
+                put("embed_data", "{\"preferred payment method\":[\"domestic card\",\"account\"],\"redirecturl\":\"cityexpressuser://\"}");
+            }
+            if(config.getPay_type().equals("4")){
+                put("bank_code", "");
+                put("embed_data", "{\"preferred payment method\":[\"vietqr\"],\"redirecturl\":\"cityexpressuser://\"}");
+            }
+
+            put("item", "[]");
+
+        }};
+
+
+        String data = order.get("app_id") +"|"+ order.get("app_trans_id") +"|"+ order.get("app_user") +"|"+ order.get("amount")
+                +"|"+ order.get("app_time") +"|"+ order.get("embed_data") +"|"+ order.get("item");
+        order.put("mac", HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data));
+        System.out.println("ZaloPay CreateOrder 创建的 order信息: " + order);
+        HttpPost post=createPost(order, apiProperties.getCreate_order_url());
+
+        // 添加日志和异常处理
+        try (CloseableHttpClient httpClient = HttpClients.createDefault();
+             CloseableHttpResponse res = httpClient.execute(post)) {
+
+            BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
+            StringBuilder resultJsonStr = new StringBuilder();
+            String line;
+
+            while ((line = rd.readLine()) != null) {
+                resultJsonStr.append(line);
+            }
+            String responseJson = resultJsonStr.toString();
+            System.out.println("ZaloPay CreateOrder Response: " + responseJson); // 日志输出
+            return JSON.parseObject(responseJson, ZaloPayCreateOrderResponse.class);
+        }
+    }
+    /**
+     * 查询订单支付状态
+     *
+     * @param appTransId 订单号
+     * @return 支付状态
+     */
+    public  ZaloPayQueryOrderResponse queryOrderStatus(String appTransId,ZaloPayProperties.ZaloPayConfig config) throws URISyntaxException, IOException {
+        String APP_ID = config.getApp_id();
+        String KEY1 = config.getKey1();
+        String data = APP_ID +"|"+ appTransId  +"|"+ KEY1; // appid|app_trans_id|key1
+        String mac = HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data);
+
+        List<NameValuePair> params = new ArrayList<>();
+        params.add(new BasicNameValuePair("app_id", APP_ID));
+        params.add(new BasicNameValuePair("app_trans_id", appTransId));
+        params.add(new BasicNameValuePair("mac", mac));
+        URIBuilder uri = new URIBuilder(apiProperties.getQuery_order_url());
+        uri.addParameters(params);
+        CloseableHttpClient client = HttpClients.createDefault();
+        HttpPost post = new HttpPost(uri.build());
+        post.setEntity(new UrlEncodedFormEntity(params));
+        CloseableHttpResponse res = client.execute(post);
+        BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
+        StringBuilder resultJsonStr = new StringBuilder();
+        String line;
+        while ((line = rd.readLine()) != null) {
+            resultJsonStr.append(line);
+        }
+        JSONObject result = JSON.parseObject(resultJsonStr.toString());
+        for (String key : result.keySet()) {
+            System.out.format("%s = %s\n", key, result.get(key));
+        }
+        System.out.println("ZaloPay QueryOrder Response: " + resultJsonStr);
+        return JSON.parseObject(resultJsonStr.toString(), ZaloPayQueryOrderResponse.class);
+    }
+
+    /**
+     * 退款
+     *
+     * @param zpTransId
+     * @param amount
+     * @return ZaloPayRefundResponse 退款响应数据
+     */
+    public  ZaloPayRefundResponse Refund(String zpTransId, long amount,String mRefundId,ZaloPayProperties.ZaloPayConfig config) throws Exception {
+        String APP_ID = config.getApp_id();
+        String KEY1 = config.getKey1();
+        String appid = APP_ID;
+        long timestamp = System.currentTimeMillis(); // miliseconds
+        Map<String, Object> order = new HashMap<String, Object>() {{
+            put("app_id", appid);
+            put("zp_trans_id", zpTransId); // 使用传入的 zpTransId
+//            put("m_refund_id", getCurrentTimeString("yyMMdd") + "_" + appid + "_" + ddId);
+            put("m_refund_id", mRefundId);
+            put("timestamp", timestamp);
+            put("amount", amount); // 使用传入的 amount
+            put("description", "ZaloPay Intergration Demo");
+        }};
+
+        // appid|zptransid|amount|description|timestamp
+        String data = order.get("app_id") + "|" + order.get("zp_trans_id") + "|" + order.get("amount")
+                + "|" + order.get("description") + "|" + order.get("timestamp");
+        order.put("mac", HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data));
+
+        CloseableHttpClient client = HttpClients.createDefault();
+        HttpPost post = createPost(order, apiProperties.getRefund_url());
+        CloseableHttpResponse res = client.execute(post);
+        BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
+        StringBuilder resultJsonStr = new StringBuilder();
+        String line;
+
+        while ((line = rd.readLine()) != null) {
+            resultJsonStr.append(line);
+        }
+        System.out.println("ZaloPay Refund Response: " + resultJsonStr.toString()); // 日志输出
+        // 解析响应数据为 ZaloPayRefundResponse 对象
+        return JSON.parseObject(resultJsonStr.toString(), ZaloPayRefundResponse.class);
+    }
+    /**
+     * 查询退款状态
+     *
+     * @param m_refund_id 退款单号
+     * @return 退款状态
+     */
+    public  ZaloPayQueryRefundResponse queryRefundStatus(String m_refund_id, ZaloPayProperties.ZaloPayConfig config) throws URISyntaxException, IOException {
+        String APP_ID = config.getApp_id();
+        String KEY1 = config.getKey1();
+        String timestamp = Long.toString(System.currentTimeMillis()); // miliseconds
+        String data = APP_ID +"|"+ m_refund_id  +"|"+ timestamp; // app_id|m_refund_id|timestamp
+        String mac = HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data);
+
+        List<NameValuePair> params = new ArrayList<>();
+        params.add(new BasicNameValuePair("app_id", APP_ID));
+        params.add(new BasicNameValuePair("m_refund_id", m_refund_id));
+        params.add(new BasicNameValuePair("timestamp", timestamp));
+        params.add(new BasicNameValuePair("mac", mac));
+        URIBuilder uri = new URIBuilder(apiProperties.getQuery_refund_url());
+        uri.addParameters(params);
+
+        CloseableHttpClient client = HttpClients.createDefault();
+        HttpPost post = new HttpPost(uri.build());
+        post.setEntity(new UrlEncodedFormEntity(params));
+
+        CloseableHttpResponse res = client.execute(post);
+        BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
+        StringBuilder resultJsonStr = new StringBuilder();
+        String line;
+
+        while ((line = rd.readLine()) != null) {
+            resultJsonStr.append(line);
+        }
+        System.out.println("ZaloPay QueryRefund Response: " + resultJsonStr);
+        return JSON.parseObject(resultJsonStr.toString(), ZaloPayQueryRefundResponse.class);
+    }
+
+
+    public static HttpPost createPost(Map<String, Object> order, String refundUrl) throws UnsupportedEncodingException {
+        HttpPost post = new HttpPost(refundUrl);
+
+        List<NameValuePair> params = new ArrayList<>();
+        for (Map.Entry<String, Object> e : order.entrySet()) {
+            params.add(new BasicNameValuePair(e.getKey(), e.getValue().toString()));
+        }
+
+        post.setEntity(new UrlEncodedFormEntity(params));
+        return post;
+    }
+}

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/utils/zaloPay/ZaloPayApiProperties.java

@@ -0,0 +1,15 @@
+package com.ruoyi.app.utils.zaloPay;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "zalo.pay.api")
+public class ZaloPayApiProperties {
+    private String create_order_url;
+    private String query_order_url;
+    private String refund_url;
+    private String query_refund_url;
+}

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