Browse Source

Merge branch 'master' of https://git.zhixinghe1.top/zkpk/PunchSettle-Server

# Conflicts:
#	.idea/inspectionProfiles/Project_Default.xml
#	.idea/misc.xml
#	pom.xml
#	src/main/java/com/punchsettle/server/atomic/entity/PunchIn.java
#	src/main/java/com/punchsettle/server/atomic/entity/PunchInRecord.java
#	src/main/java/com/punchsettle/server/atomic/entity/PunchInRecordSettlementRela.java
#	src/main/java/com/punchsettle/server/atomic/entity/PunchInSettlement.java
#	src/main/java/com/punchsettle/server/atomic/entity/SettlementNotifyTask.java
#	src/main/java/com/punchsettle/server/atomic/entity/SettlementTask.java
#	src/main/java/com/punchsettle/server/atomic/entity/User.java
#	src/main/java/com/punchsettle/server/atomic/mapper/PunchInMapper.java
#	src/main/java/com/punchsettle/server/atomic/mapper/PunchInRecordMapper.java
#	src/main/java/com/punchsettle/server/atomic/service/impl/PunchInRecordServiceImpl.java
#	src/main/java/com/punchsettle/server/common/entity/BaseEntity.java
#	src/main/java/com/punchsettle/server/core/config/TkMyBatisConfig.java
#	src/main/resources/application.yaml
ChenYL 1 year ago
parent
commit
cf9db26c4e
89 changed files with 3543 additions and 225 deletions
  1. 12 0
      .idea/eclipseCodeFormatter.xml
  2. 0 1
      .idea/encodings.xml
  3. 3 0
      .idea/inspectionProfiles/Project_Default.xml
  4. 1 1
      .idea/misc.xml
  5. 26 0
      README.md
  6. 603 0
      doc/eclipse-codestyle.xml
  7. 49 11
      doc/sql/schema.sql
  8. 142 68
      doc/技术文档.md
  9. 5 17
      pom.xml
  10. 9 5
      src/main/java/com/punchsettle/server/atomic/entity/PunchIn.java
  11. 38 0
      src/main/java/com/punchsettle/server/atomic/entity/PunchInRecord.java
  12. 38 0
      src/main/java/com/punchsettle/server/atomic/entity/PunchInRecordSettlementRela.java
  13. 81 0
      src/main/java/com/punchsettle/server/atomic/entity/PunchInSettlement.java
  14. 67 0
      src/main/java/com/punchsettle/server/atomic/entity/SettlementNotifyTask.java
  15. 63 0
      src/main/java/com/punchsettle/server/atomic/entity/SettlementTask.java
  16. 44 0
      src/main/java/com/punchsettle/server/atomic/entity/User.java
  17. 57 0
      src/main/java/com/punchsettle/server/atomic/entity/UserClaimRewardRecord.java
  18. 50 0
      src/main/java/com/punchsettle/server/atomic/entity/UserReward.java
  19. 6 4
      src/main/java/com/punchsettle/server/atomic/mapper/PunchInMapper.java
  20. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/PunchInRecordMapper.java
  21. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/PunchInRecordSettlementRelaMapper.java
  22. 15 0
      src/main/java/com/punchsettle/server/atomic/mapper/PunchInSettlementMapper.java
  23. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/SettlementNotifyTaskMapper.java
  24. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/SettlementTaskMapper.java
  25. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/UserClaimRewardRecordMapper.java
  26. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/UserMapper.java
  27. 15 0
      src/main/java/com/punchsettle/server/atomic/mapper/UserRewardMapper.java
  28. 28 0
      src/main/java/com/punchsettle/server/atomic/service/IPunchInRecordService.java
  29. 20 0
      src/main/java/com/punchsettle/server/atomic/service/IPunchInRecordSettlementRelaService.java
  30. 47 0
      src/main/java/com/punchsettle/server/atomic/service/IPunchInService.java
  31. 20 0
      src/main/java/com/punchsettle/server/atomic/service/IPunchInSettlementService.java
  32. 24 0
      src/main/java/com/punchsettle/server/atomic/service/ISettlementTaskService.java
  33. 18 0
      src/main/java/com/punchsettle/server/atomic/service/IUserClaimRewardRecordService.java
  34. 40 0
      src/main/java/com/punchsettle/server/atomic/service/IUserRewardService.java
  35. 34 0
      src/main/java/com/punchsettle/server/atomic/service/IUserService.java
  36. 46 3
      src/main/java/com/punchsettle/server/atomic/service/impl/PunchInRecordServiceImpl.java
  37. 33 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PunchInRecordSettlementRelaServiceImpl.java
  38. 76 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PunchInServiceImpl.java
  39. 30 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PunchInSettlementServiceImpl.java
  40. 34 0
      src/main/java/com/punchsettle/server/atomic/service/impl/SettlementTaskServiceImpl.java
  41. 28 0
      src/main/java/com/punchsettle/server/atomic/service/impl/UserClaimRewardRecordServiceImpl.java
  42. 69 0
      src/main/java/com/punchsettle/server/atomic/service/impl/UserRewardServiceImpl.java
  43. 50 0
      src/main/java/com/punchsettle/server/atomic/service/impl/UserServiceImpl.java
  44. 2 2
      src/main/java/com/punchsettle/server/common/converter/enums/IntegerToEnumConverter.java
  45. 3 3
      src/main/java/com/punchsettle/server/common/converter/enums/IntegerToEnumConverterFactory.java
  46. 5 4
      src/main/java/com/punchsettle/server/common/dto/JsonResponse.java
  47. 9 7
      src/main/java/com/punchsettle/server/common/entity/BaseEntity.java
  48. 72 0
      src/main/java/com/punchsettle/server/common/utils/Assert.java
  49. 10 0
      src/main/java/com/punchsettle/server/common/valid/Delete.java
  50. 10 0
      src/main/java/com/punchsettle/server/common/valid/DoSomething.java
  51. 10 0
      src/main/java/com/punchsettle/server/common/valid/Query.java
  52. 10 0
      src/main/java/com/punchsettle/server/common/valid/Save.java
  53. 10 0
      src/main/java/com/punchsettle/server/common/valid/Update.java
  54. 36 0
      src/main/java/com/punchsettle/server/constant/PunchInStatusEnum.java
  55. 39 5
      src/main/java/com/punchsettle/server/core/aop/GlobalExceptionHandler.java
  56. 5 4
      src/main/java/com/punchsettle/server/core/aop/ResponseControllerAdvice.java
  57. 4 3
      src/main/java/com/punchsettle/server/core/aop/WebOperateLogAspect.java
  58. 2 1
      src/main/java/com/punchsettle/server/core/config/BizConfig.java
  59. 6 5
      src/main/java/com/punchsettle/server/core/config/FeignConfig.java
  60. 19 1
      src/main/java/com/punchsettle/server/core/config/TkMyBatisConfig.java
  61. 24 3
      src/main/java/com/punchsettle/server/core/config/WebMvcConfig.java
  62. 43 27
      src/main/java/com/punchsettle/server/core/interceptor/AuthInterceptor.java
  63. 118 0
      src/main/java/com/punchsettle/server/core/interceptor/MybatisAuditDataInterceptor.java
  64. 20 0
      src/main/java/com/punchsettle/server/dto/ClaimRewardDto.java
  65. 65 0
      src/main/java/com/punchsettle/server/dto/PunchInDto.java
  66. 27 0
      src/main/java/com/punchsettle/server/dto/PunchInRecordDto.java
  67. 32 0
      src/main/java/com/punchsettle/server/dto/PunchInRecordQuery.java
  68. 50 0
      src/main/java/com/punchsettle/server/dto/PunchInWithRecordDto.java
  69. 18 0
      src/main/java/com/punchsettle/server/dto/UserRewardDto.java
  70. 1 0
      src/main/java/com/punchsettle/server/dto/wechat/Code2SessionResponse.java
  71. 3 2
      src/main/java/com/punchsettle/server/feign/WechatMiniProgramFeign.java
  72. 10 10
      src/main/java/com/punchsettle/server/service/controller/LoginController.java
  73. 79 0
      src/main/java/com/punchsettle/server/service/controller/PunchInController.java
  74. 44 0
      src/main/java/com/punchsettle/server/service/controller/RewardController.java
  75. 30 0
      src/main/java/com/punchsettle/server/service/controller/TaskController.java
  76. 3 3
      src/main/java/com/punchsettle/server/service/manager/ILoginManager.java
  77. 44 0
      src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java
  78. 25 0
      src/main/java/com/punchsettle/server/service/manager/IRewardManager.java
  79. 15 0
      src/main/java/com/punchsettle/server/service/manager/ITaskManager.java
  80. 22 24
      src/main/java/com/punchsettle/server/service/manager/impl/LoginManagerImpl.java
  81. 173 0
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java
  82. 81 0
      src/main/java/com/punchsettle/server/service/manager/impl/RewardManagerImpl.java
  83. 224 0
      src/main/java/com/punchsettle/server/service/manager/impl/TaskManagerImpl.java
  84. 82 0
      src/main/java/com/punchsettle/server/utiis/DateUtils.java
  85. 3 3
      src/main/java/com/punchsettle/server/utiis/TokenUtils.java
  86. 28 0
      src/main/java/com/punchsettle/server/utiis/UserUtils.java
  87. 12 0
      src/main/resources/application-dev.yaml
  88. 8 0
      src/main/resources/application-prod.yaml
  89. 2 8
      src/main/resources/application.yaml

+ 12 - 0
.idea/eclipseCodeFormatter.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="EclipseCodeFormatterProjectSettings">
+    <option name="projectSpecificProfile">
+      <ProjectSpecificProfile>
+        <option name="formatter" value="ECLIPSE" />
+        <option name="pathToConfigFileJava" value="$PROJECT_DIR$/doc/eclipse-codestyle.xml" />
+        <option name="selectedJavaProfile" value="P3C-CodeStyle" />
+      </ProjectSpecificProfile>
+    </option>
+  </component>
+</project>

+ 0 - 1
.idea/encodings.xml

@@ -2,6 +2,5 @@
 <project version="4">
 <project version="4">
   <component name="Encoding">
   <component name="Encoding">
     <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
   </component>
   </component>
 </project>
 </project>

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

@@ -63,6 +63,9 @@
     <inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavadocDeclaration" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ADDITIONAL_TAGS" value="ClassName,Date,Author,Version,Description,className,description,date" />
+    </inspection_tool>
     <inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SerializableHasSerialVersionUIDField" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SerializableHasSerialVersionUIDField" enabled="true" level="WARNING" enabled_by_default="true" />
   </profile>
   </profile>

+ 1 - 1
.idea/misc.xml

@@ -9,7 +9,7 @@
     </option>
     </option>
     <option name="workspaceImportForciblyTurnedOn" value="true" />
     <option name="workspaceImportForciblyTurnedOn" value="true" />
   </component>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
     <output url="file://$PROJECT_DIR$/out" />
   </component>
   </component>
 </project>
 </project>

+ 26 - 0
README.md

@@ -0,0 +1,26 @@
+# 打卡结算
+
+
+
+## 各种位置
+
+前端项目:[PunchSettle-MiniProgram](https://git.zhixinghe1.top/zkpk/PunchSettle-MiniProgram)
+
+文档:doc/技术文档.md
+
+数据库脚本:doc/sql
+
+
+
+## 待办列表
+
+* uniapp环境配置分离
+* 对接前端
+* certbot自动续期
+* 结算任务增加定时任务自动执行
+* 数据库脚本审计字段(creation_time、last_update_time)增加默认值
+* ~~功能开发~~
+* ~~前端开发~~
+* ~~表设计~~
+* ~~前端原型图设计~~
+* ~~需求文档编写~~

+ 603 - 0
doc/eclipse-codestyle.xml

@@ -0,0 +1,603 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="12">
+    <profile kind="CodeFormatterProfile" name="P3C-CodeStyle" version="13">
+        <!--可变参数的... Idea没有对应的配置项,强制insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+        <!--枚举值之间 Idea没有对应的配置项,强制insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=Java:SPACE_BEFORE_COMMA-->
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=Java:SPACE_BEFORE_COMMA
+        由于IDEA只有一个SPACE_BEFORE_COMMA选项,所以统一设置 insert_space_before_comma 为 do not insert
+        -->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments"
+                 value="do not insert"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations"
+                 value="do not insert"/>
+        <!--insert_space_before_comma end-->
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=Java:SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+        <!--IDEA只有一个配置项SPACE_AFTER_COMMA,insert_space_after_comma*统一设置成insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+        <!--insert_space_after_comma end-->
+
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=Java:SPACE_BEFORE_COLON-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=Java:SPACE_AFTER_COLON-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+
+        <!--IDEA不支持配置,默认do not insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+        <!--这个在Eclipse也没有找到配置的地方-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="do not insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_semicolon=Java:SPACE_BEFORE_SEMICOLON
+        程序导入的时候强制将SPACE_BEFORE_SEMICOLON设置为false
+        -->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+
+        <!--SPACE_AFTER_SEMICOLON=true-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
+
+        <!--IDEA不支持配置,do not insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
+                 value="do not insert"/>
+        <setting
+                id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
+                value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
+                 value="do not insert"/>
+
+        <!--IDEA不支持,使用默认-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+
+        <!--IDEA不支持配置,使用如下值,两者对应-->
+        <setting
+                id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference"
+                value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
+                 value="do not insert"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
+                 value="insert"/>
+        <setting
+                id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
+                value="do not insert"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
+                 value="do not insert"/>
+        <setting
+                id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
+                value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
+                 value="do not insert"/>
+
+        <!--Java:SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
+                 value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=Java:SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
+                 value="do not insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+
+        <!--IDEA使用了对应的配置:Java:SPACE_WITHIN_ARRAY_INITIALIZER_BRACES,但感觉不太好,IDEA默认不插入,Eclipse也使用不插入-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
+                 value="do not insert"/>
+
+        <!--use default insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return"
+                 value="insert"/>
+
+        <!--use default do not insert -->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+
+
+        <!--use default insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration"
+                 value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw"
+                 value="insert"/>
+
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=Java:SPACE_BEFORE_SWITCH_LBRACE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=Java:SPACE_BEFORE_CLASS_LBRACE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration"
+                 value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=Java:SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer"
+                 value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=Java:SPACE_BEFORE_METHOD_LBRACE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
+                 value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=Java:SPACE_AFTER_QUEST-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=Java:SPACE_BEFORE_QUEST-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=Java:SPACE_BEFORE_ANOTATION_PARAMETER_LIST-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation"
+                 value="do not insert"/>
+
+        <!--use default do not insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+        <setting
+                id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
+                value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
+                 value="do not insert"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference"
+                 value="do not insert"/>
+
+
+        <!--下面两个对应IDEA中的一个配置Java:SPACE_AROUND_ASSIGNMENT_OPERATORS,使用insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=Java:SPACE_BEFORE_CATCH_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=Java:SPACE_BEFORE_METHOD_CALL_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation"
+                 value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=Java:SPACE_BEFORE_TRY_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
+
+        <!--下面两个对应IDEA中的一个配置Java:SPACE_AROUND_UNARY_OPERATOR,使用do not insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=Java:SPACE_BEFORE_IF_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=Java:SPACE_BEFORE_WHILE_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=Java:SPACE_AFTER_TYPE_CAST-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="do not insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=Java:SPACE_BEFORE_METHOD_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration"
+                 value="do not insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=Java:SPACE_BEFORE_FOR_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=Java:SPACE_BEFORE_SYNCHRONIZED_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+
+        <!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=Java:SPACE_BEFORE_SWITCH_PARENTHESES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+
+        <!--下面两个对应IDEA中的一个配置Java:SPACE_AROUND_LAMBDA_ARROW,使用insert-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
+        <!--SPACE_WITHIN_EMPTY_ARRAY_INITIALIZER_BRACES-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer"
+                 value="do not insert"/>
+
+        <!--Idea -> Wrapping And Braces -> Simple classes in one line -->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
+        <!--Idea -> Wrapping And Braces -> Simple method in one line -->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
+        <!--因为Idea不支持配置,所以设置为 Idea默认值-->
+
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant"
+                 value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
+        <!--Idea可以通过Wrap Always实现 TODO-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+        <!--Idea -> Wrapping And Braces -> Simple block in one line -> do not select -->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+
+        <!--Idea -> Wrapping And Braces -> try statement -> catch.... (Java:CATCH_ON_NEW_LINE)-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement"
+                 value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=Java:ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer"
+                 value="do not insert"/>
+        <!--#org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer"
+                 value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=Java:ELSE_ON_NEW_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=Java:WHILE_ON_NEW_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement"
+                 value="do not insert"/>
+        <!--org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=Java:FINALLY_ON_NEW_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement"
+                 value="do not insert"/>
+
+        <!--comment start-->
+        <setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+        <!--ENABLE_JAVADOC_FORMATTING-->
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+        <!--org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+        <!--IDEA无对应设置,所以关闭对block comment的格式化 -->
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+
+        <!--org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=Java:KEEP_FIRST_COLUMN_COMMENT-->
+        <setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+        <!--org.eclipse.jdt.core.formatter.use_on_off_tags=FORMATTER_TAGS_ENABLED-->
+        <setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
+        <!--org.eclipse.jdt.core.formatter.disabling_tag=FORMATTER_OFF_TAG-->
+        <setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
+        <!--org.eclipse.jdt.core.formatter.enabling_tag=FORMATTER_ON_TAG-->
+        <setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+
+        <!--下面的没有IDEA对应项,在代码里面对IDEA中使用默认值即可,LINE_COMMENT_AT_FIRST_COLUMN BLOCK_COMMENT_AT_FIRST_COLUMN设置为false-->
+        <setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments"
+                 value="false"/>
+
+
+        <setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+        <!--和IDEA保持一致,注释换行-->
+        <setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
+
+
+        <!--comment end-->
+
+        <!--org.eclipse.jdt.core.formatter.blank_lines_after_imports=Java:BLANK_LINES_AFTER_IMPORTS-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_before_imports=Java:BLANK_LINES_BEFORE_IMPORTS-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_after_package=Java:BLANK_LINES_AFTER_PACKAGE-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=Java:BLANK_LINES_AROUND_CLASS-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+        <!--org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=Java:BLANK_LINES_BEFORE_METHOD_BODY-->
+        <setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_before_field=Java:BLANK_LINES_AROUND_FIELD-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_before_method=Java:BLANK_LINES_AROUND_METHOD-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+        <!--org.eclipse.jdt.core.formatter.blank_lines_before_package=Java:BLANK_LINES_BEFORE_PACKAGE-->
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+
+        <!--下面IDEA没有对应设置,使用对应值即可-->
+        <setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+
+        <!--org.eclipse.jdt.core.formatter.indentation.size=Java:IndentOptions:INDENT_SIZE-->
+        <setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+        <!--org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/>
+        <!--org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+        <!--org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=Java:IndentOptions:SMART_TABS-->
+        <setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+        <!--org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=Java:INDENT_CASE_FROM_SWITCH-->
+        <setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+        <!--KEEP_INDENTS_ON_EMPTY_LINES-->
+        <setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+        <!--org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+        <!--Java:IndentOptions:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+
+
+        <!--下面IDEA没有对应设置,使用对应值即可-->
+        <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
+                 value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
+                 value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header"
+                 value="true"/>
+
+
+        <!--Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+
+        <!--下面没有对应的IDEA设置,Eclipse先使用对应值-->
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="16"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+
+
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression"
+                 value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="16"/>
+
+        <!--IDEA默认配置在同一行,Eclipse使用对应值即可-->
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration"
+                 value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
+        <setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
+
+        <!--Java:BINARY_OPERATION_SIGN_ON_NEXT_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+
+        <!--ASSIGNMENT_WRAP 需要设置为 WRAP_AS_NEEDED  WRAP_AS_NEEDED . Add in jdt.core-3.12,it's not work in previous version -->
+        <setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
+
+        <!--IDEA无配置项,Eclipse使用对应值即可-->
+        <setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+
+        <!--org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=Java:KEEP_CONTROL_STATEMENT_IN_ONE_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+        <!--org.eclipse.jdt.core.formatter.compact_else_if=Java:SPECIAL_ELSE_IF_TREATMENT-->
+        <setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+        <!--Java:ALIGN_GROUP_FIELD_DECLARATIONS-->
+        <setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+        <!--Java:<Programmatic>-->
+        <setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+
+        <!--统一为end_of_lint,IDEA默认一致-->
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration"
+                 value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+
+
+        <!--        <setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
+                <setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
+                <setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
+                        <setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+                                <setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+                                        <setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+                -->
+        <!--Java:KEEP_SIMPLE_BLOCKS_IN_ONE_LINE-->
+        <setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+
+        <!--Java:CLASS_BRACE_STYLE,统一使用end_of_line TODO-->
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+
+        <!--org.eclipse.jdt.core.formatter.lineSplit=RIGHT_MARGIN-->
+        <setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+    </profile>
+</profiles>

+ 49 - 11
doc/sql/schema.sql

@@ -21,7 +21,7 @@ CREATE TABLE `punch_in` (
 CREATE TABLE `punch_in_record` (
 CREATE TABLE `punch_in_record` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `punch_in_id` bigint NOT NULL COMMENT '打卡任务表主键',
   `punch_in_id` bigint NOT NULL COMMENT '打卡任务表主键',
-  `punch_in_time` timestamp NOT NULL COMMENT '打卡时间',
+  `punch_in_date` varchar(10) NOT NULL COMMENT '打卡日期',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `creation_time` timestamp NOT NULL COMMENT '创建时间',
   `creation_time` timestamp NOT NULL COMMENT '创建时间',
   `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
   `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
@@ -31,7 +31,6 @@ CREATE TABLE `punch_in_record` (
   PRIMARY KEY (`id`)
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='打卡任务记录表';
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='打卡任务记录表';
 
 
-
 -- punch_settle.punch_in_record_settlement_rela definition
 -- punch_settle.punch_in_record_settlement_rela definition
 
 
 CREATE TABLE `punch_in_record_settlement_rela` (
 CREATE TABLE `punch_in_record_settlement_rela` (
@@ -53,9 +52,9 @@ CREATE TABLE `punch_in_record_settlement_rela` (
 CREATE TABLE `punch_in_settlement` (
 CREATE TABLE `punch_in_settlement` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `user_id` bigint NOT NULL COMMENT '用户表主键',
   `user_id` bigint NOT NULL COMMENT '用户表主键',
-  `reward_num` int NOT NULL COMMENT '结算奖励数',
-  `claim_reward_flag` tinyint NOT NULL DEFAULT '0' COMMENT '是否已领取奖励(0-未领取,1-已领取)',
-  `claim_reward_time` timestamp NULL DEFAULT NULL COMMENT '领取奖励时间',
+  `settle_reward_num` int NOT NULL COMMENT '结算奖励数',
+  `before_settle_reward_num` int NOT NULL DEFAULT '0' COMMENT '结算前用户拥有的奖励数',
+  `after_settle_reward_num` int NOT NULL DEFAULT '0' COMMENT '结算后用户拥有的奖励数',
   `settlement_task_id` bigint NOT NULL COMMENT '结算任务表id',
   `settlement_task_id` bigint NOT NULL COMMENT '结算任务表id',
   `settlement_time` timestamp NOT NULL COMMENT '结算时间',
   `settlement_time` timestamp NOT NULL COMMENT '结算时间',
   `notify_id` bigint DEFAULT NULL COMMENT '通知表ID',
   `notify_id` bigint DEFAULT NULL COMMENT '通知表ID',
@@ -96,12 +95,12 @@ CREATE TABLE `settlement_notify_task` (
 
 
 CREATE TABLE `settlement_task` (
 CREATE TABLE `settlement_task` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `settle_date` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '结算日期',
   `start_time` timestamp NULL DEFAULT NULL COMMENT '任务开始时间',
   `start_time` timestamp NULL DEFAULT NULL COMMENT '任务开始时间',
   `end_time` timestamp NULL DEFAULT NULL COMMENT '任务结束时间',
   `end_time` timestamp NULL DEFAULT NULL COMMENT '任务结束时间',
-  `task_status` varchar(20) NOT NULL DEFAULT 'processing' COMMENT '任务状态(success-成功,fail-失败,processing-处理中)',
-  `processed_num` int NOT NULL DEFAULT '0' COMMENT '处理数量',
-  `processed_success_num` int NOT NULL DEFAULT '0' COMMENT '处理成功数量',
-  `processed_fail_num` int NOT NULL DEFAULT '0' COMMENT '处理失败数量',
+  `processed_num` int NOT NULL DEFAULT '0' COMMENT '待处理结算数量',
+  `processed_settle_num` int NOT NULL DEFAULT '0' COMMENT '处理已结算数量',
+  `processed_unsettle_num` int NOT NULL DEFAULT '0' COMMENT '处理没结算数量',
   `error_message` text COMMENT '失败异常信息',
   `error_message` text COMMENT '失败异常信息',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `creation_time` timestamp NOT NULL COMMENT '创建时间',
   `creation_time` timestamp NOT NULL COMMENT '创建时间',
@@ -119,7 +118,46 @@ CREATE TABLE `user` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `open_id` varchar(128) NOT NULL COMMENT '微信id',
   `open_id` varchar(128) NOT NULL COMMENT '微信id',
   `nickname` varchar(100) DEFAULT NULL COMMENT '微信昵称',
   `nickname` varchar(100) DEFAULT NULL COMMENT '微信昵称',
-  `avator` varchar(1000) DEFAULT NULL COMMENT '微信头像url',
+  `avatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '微信头像url',
+  `reward_num` int NOT NULL DEFAULT '0',
+  `claimed_reward_num` int NOT NULL DEFAULT '0' COMMENT '已领取奖励数',
+  `created_by` bigint NOT NULL COMMENT '创建人',
+  `creation_time` timestamp NOT NULL COMMENT '创建时间',
+  `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
+  `last_update_time` timestamp NOT NULL COMMENT '最后更新时间',
+  `version` bigint NOT NULL DEFAULT '1' COMMENT '版本号',
+  `delete_flag` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标志(0-未删除,1-已删除)',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
+
+
+-- punch_settle.user_reward definition
+
+CREATE TABLE `user_reward` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `user_id` bigint NOT NULL COMMENT '用户表主键',
+  `total_reward_num` int NOT NULL COMMENT '总奖励数',
+  `unclaimed_reward_num` int NOT NULL DEFAULT '0' COMMENT '未领取奖励数',
+  `claimed_reward_num` int NOT NULL DEFAULT '0' COMMENT '已领取奖励数',
+  `created_by` bigint NOT NULL COMMENT '创建人',
+  `creation_time` timestamp NOT NULL COMMENT '创建时间',
+  `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
+  `last_update_time` timestamp NOT NULL COMMENT '最后更新时间',
+  `version` bigint NOT NULL DEFAULT '1' COMMENT '版本号',
+  `delete_flag` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标志(0-未删除,1-已删除)',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=' 用户奖励数据表';
+
+
+-- punch_settle.user_claim_reward_record definition
+
+CREATE TABLE `user_claim_reward_record` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `user_id` bigint NOT NULL COMMENT '用户表主键',
+  `claim_reward_num` int NOT NULL DEFAULT '0' COMMENT '本次领取奖励数',
+  `claim_reward_time` timestamp NOT NULL COMMENT '领取奖励时间',
+  `before_claim_reward_num` int NOT NULL DEFAULT '0' COMMENT '领取前用户拥有的奖励数',
+  `after_claim_reward_num` int NOT NULL DEFAULT '0' COMMENT '领取后用户拥有的奖励数',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `creation_time` timestamp NOT NULL COMMENT '创建时间',
   `creation_time` timestamp NOT NULL COMMENT '创建时间',
   `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
   `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
@@ -127,4 +165,4 @@ CREATE TABLE `user` (
   `version` bigint NOT NULL DEFAULT '1' COMMENT '版本号',
   `version` bigint NOT NULL DEFAULT '1' COMMENT '版本号',
   `delete_flag` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标志(0-未删除,1-已删除)',
   `delete_flag` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标志(0-未删除,1-已删除)',
   PRIMARY KEY (`id`)
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='领取奖励记录表';

+ 142 - 68
doc/技术文档.md

@@ -6,7 +6,7 @@ ui设计工具:即时设计
 
 
 小程序框架:uniapp
 小程序框架:uniapp
 
 
-后端框架:spring boot + mybatis + mybatis mapper + spring mvc
+后端框架:spring boot + mybatis + tk mybatis+ spring mvc
 
 
 数据库:mysql
 数据库:mysql
 
 
@@ -28,10 +28,16 @@ ui设计工具:即时设计
 
 
 * 打卡任务
 * 打卡任务
 
 
-  1. 新建任务
-  2. 编辑任务
-  3. 删除任务
-  4. 用户完成任务
+  1. 查询当前用户拥有的打卡任务列表
+  2. 新建任务
+  3. 编辑任务
+  4. 删除任务
+  5. 用户完成任务
+
+* 奖励
+
+  1. 查询当前用户拥有的奖励数
+  2. 领取奖励
 
 
 * 系统
 * 系统
 
 
@@ -39,7 +45,7 @@ ui设计工具:即时设计
 
 
      说明:每日凌晨把昨天完成的任务获得的奖励进行自动统计
      说明:每日凌晨把昨天完成的任务获得的奖励进行自动统计
 
 
-  2. 每天自动推送结算通知
+  2. 每天自动推送结算通知(第二版再增加这个功能)
 
 
      说明:把每日结算结果推送到微信
      说明:把每日结算结果推送到微信
 
 
@@ -58,7 +64,7 @@ ui设计工具:即时设计
 | id               | bigint        | 主键                               |
 | id               | bigint        | 主键                               |
 | open_id          | varchar(128)  | 微信id                             |
 | open_id          | varchar(128)  | 微信id                             |
 | nickname         | varchar(100)  | 微信昵称                           |
 | nickname         | varchar(100)  | 微信昵称                           |
-| avator           | varchar(1000) | 微信头像url                        |
+| avatar           | varchar(1000) | 微信头像url                        |
 | created_by       | bigint        | 创建人                             |
 | created_by       | bigint        | 创建人                             |
 | creation_time    | timestamp     | 创建时间                           |
 | creation_time    | timestamp     | 创建时间                           |
 | last_updated_by  | bigint        | 最后更新人                         |
 | last_updated_by  | bigint        | 最后更新人                         |
@@ -93,17 +99,17 @@ ui设计工具:即时设计
 
 
 表名:punch_in_record
 表名:punch_in_record
 
 
-| 字段             | 类型      | 描述                               |
-| ---------------- | --------- | ---------------------------------- |
-| id               | bigint    | 主键                               |
-| punch_in_id      | bigint    | 打卡任务表主键                     |
-| punch_in_time    | timestamp | 打卡时间                           |
-| created_by       | bigint    | 创建人                             |
-| creation_time    | timestamp | 创建时间                           |
-| last_updated_by  | bigint    | 最后更信人                         |
-| last_update_time | timestamp | 最后更新时间                       |
-| version          | bigint    | 版本号                             |
-| delete_flag      | tinyint   | 逻辑删除标志(0-未删除,1-已删除) |
+| 字段             | 类型        | 描述                               |
+| ---------------- | ----------- | ---------------------------------- |
+| id               | bigint      | 主键                               |
+| punch_in_id      | bigint      | 打卡任务表主键                     |
+| punch_in_date    | varchar(10) | 打卡日期                           |
+| created_by       | bigint      | 创建人                             |
+| creation_time    | timestamp   | 创建时间                           |
+| last_updated_by  | bigint      | 最后更信人                         |
+| last_update_time | timestamp   | 最后更新时间                       |
+| version          | bigint      | 版本号                             |
+| delete_flag      | tinyint     | 逻辑删除标志(0-未删除,1-已删除) |
 
 
 
 
 
 
@@ -111,24 +117,24 @@ ui设计工具:即时设计
 
 
 表名:punch_in_settlement
 表名:punch_in_settlement
 
 
-| 字段               | 类型        | 描述                                                         |
-| ------------------ | ----------- | ------------------------------------------------------------ |
-| id                 | bigint      | 主键                                                         |
-| user_id            | bigint      | 用户表主键                                                   |
-| reward_num         | int         | 结算奖励数                                                   |
-| claim_reward_flag  | tinyint     | 是否已领取奖励(0-未领取,1-已领取)                           |
-| claim_reward_time  | timestamp   | 领取奖励时间                                                 |
-| settlement_task_id | bigint      | 结算任务表id                                                 |
-| settlement_time    | timestamp   | 结算时间                                                     |
-| notify_id          | bigint      | 通知表ID                                                     |
-| notify_status      | varchar(20) | 结算通知状态(fail-通知失败,success-成功通知,pending-待通知) |
-| notify_time        | timestamp   | 结算通知时间                                                 |
-| created_by         | bigint      | 创建人                                                       |
-| creation_time      | timestamp   | 创建时间                                                     |
-| last_updated_by    | bigint      | 最后更信人                                                   |
-| last_update_time   | timestamp   | 最后更新时间                                                 |
-| version            | bigint      | 版本号                                                       |
-| delete_flag        | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                           |
+| 字段                     | 类型        | 描述                                                         |
+| ------------------------ | ----------- | ------------------------------------------------------------ |
+| id                       | bigint      | 主键                                                         |
+| user_id                  | bigint      | 用户表主键                                                   |
+| settle_reward_num        | int         | 结算奖励数                                                   |
+| before_settle_reward_num | int         | 结算前用户拥有的奖励数                                       |
+| after_settle_reward_num  | int         | 结算后用户拥有的奖励数                                       |
+| settlement_task_id       | bigint      | 结算任务表id                                                 |
+| settlement_time          | timestamp   | 结算时间                                                     |
+| notify_id                | bigint      | 通知表ID                                                     |
+| notify_status            | varchar(20) | 结算通知状态(fail-通知失败,success-成功通知,pending-待通知) |
+| notify_time              | timestamp   | 结算通知时间                                                 |
+| created_by               | bigint      | 创建人                                                       |
+| creation_time            | timestamp   | 创建时间                                                     |
+| last_updated_by          | bigint      | 最后更信人                                                   |
+| last_update_time         | timestamp   | 最后更新时间                                                 |
+| version                  | bigint      | 版本号                                                       |
+| delete_flag              | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                           |
 
 
 
 
 
 
@@ -150,26 +156,67 @@ ui设计工具:即时设计
 
 
 
 
 
 
+#### 用户奖励数据表
+
+表名:user_reward
+
+| 字段                 | 类型      | 描述                               |
+| -------------------- | --------- | ---------------------------------- |
+| id                   | bigint    | 主键                               |
+| user_id              | bigint    | 用户表主键                         |
+| total_reward_num     | int       | 总奖励数                           |
+| unclaimed_reward_num | int       | 未领取奖励数                       |
+| claimed_reward_num   | int       | 已领取奖励数                       |
+| created_by           | bigint    | 创建人                             |
+| creation_time        | timestamp | 创建时间                           |
+| last_updated_by      | bigint    | 最后更新人                         |
+| last_update_time     | timestamp | 最后更新时间                       |
+| version              | bigint    | 版本号                             |
+| delete_flag          | tinyint   | 逻辑删除标志(0-未删除,1-已删除) |
+
+
+
+#### 领取奖励记录表
+
+表名:user_claim_reward_record
+
+| 字段                    | 类型      | 描述                               |
+| ----------------------- | --------- | ---------------------------------- |
+| id                      | bigint    | 主键                               |
+| user_id                 | bigint    | 用户表主键                         |
+| claim_reward_num        | int       | 本次领取奖励数                     |
+| claim_reward_time       | timestamp | 领取奖励时间                       |
+| before_claim_reward_num | int       | 领取前用户拥有的奖励数             |
+| after_claim_reward_num  | int       | 领取后用户拥有的奖励数             |
+| created_by              | bigint    | 创建人                             |
+| creation_time           | timestamp | 创建时间                           |
+| last_updated_by         | bigint    | 最后更信人                         |
+| last_update_time        | timestamp | 最后更新时间                       |
+| version                 | bigint    | 版本号                             |
+| delete_flag             | tinyint   | 逻辑删除标志(0-未删除,1-已删除) |
+
+
+
 #### 奖励结算定时任务执行记录表
 #### 奖励结算定时任务执行记录表
 
 
 表名:settlement_task
 表名:settlement_task
 
 
-| 字段                  | 类型        | 描述                                                 |
-| --------------------- | ----------- | ---------------------------------------------------- |
-| id                    | bigint      | 主键                                                 |
-| start_time            | timestamp   | 任务开始时间                                         |
-| end_time              | timestamp   | 任务结束时间                                         |
-| task_status           | varchar(20) | 任务状态(success-成功,fail-失败,processing-处理中) |
-| processed_num         | int         | 处理数量                                             |
-| processed_success_num | int         | 处理成功数量                                         |
-| processed_fail_num    | int         | 处理失败数量                                         |
-| error_message         | text        | 失败异常信息                                         |
-| created_by            | bigint      | 创建人                                               |
-| creation_time         | timestamp   | 创建时间                                             |
-| last_updated_by       | bigint      | 最后更信人                                           |
-| last_update_time      | timestamp   | 最后更新时间                                         |
-| version               | bigint      | 版本号                                               |
-| delete_flag           | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                   |
+| 字段                   | 类型        | 描述                               |
+| ---------------------- | ----------- | ---------------------------------- |
+| id                     | bigint      | 主键                               |
+| settle_date            | varchar(10) | 结算日期                           |
+| start_time             | timestamp   | 任务开始时间                       |
+| end_time               | timestamp   | 任务结束时间                       |
+| processed_num          | int         | 处理结算数量                     |
+| processed_settle_num   | int         | 处理已结算数量                     |
+| processed_unsettle_num | int         | 处理没结算数量                     |
+| error_message          | text        | 失败异常信息                       |
+| created_by             | bigint      | 创建人                             |
+| creation_time          | timestamp   | 创建时间                           |
+| last_updated_by        | bigint      | 最后更信人                         |
+| last_update_time       | timestamp   | 最后更新时间                       |
+| version                | bigint      | 版本号                             |
+| delete_flag            | tinyint     | 逻辑删除标志(0-未删除,1-已删除) |
 
 
 
 
 
 
@@ -177,22 +224,29 @@ ui设计工具:即时设计
 
 
 表名:settlement_notify_task
 表名:settlement_notify_task
 
 
-| 字段               | 类型        | 描述                                                 |
-| ------------------ | ----------- | ---------------------------------------------------- |
-| id                 | bigint      | 主键                                                 |
-| start_time         | timestamp   | 任务开始时间                                         |
-| end_time           | timestamp   | 任务结束时间                                         |
-| task_status        | varchar(20) | 任务状态(success-成功,fail-失败,processing-处理中) |
-| notify_num         | int         | 通知数量                                             |
-| notify_success_num | int         | 通知成功数量                                         |
-| notify_fail_num    | int         | 通知失败数量                                         |
-| error_message      | text        | 失败异常信息                                         |
-| created_by         | bigint      | 创建人                                               |
-| creation_time      | timestamp   | 创建时间                                             |
-| last_updated_by    | bigint      | 最后更信人                                           |
-| last_update_time   | timestamp   | 最后更新时间                                         |
-| version            | bigint      | 版本号                                               |
-| delete_flag        | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                   |
+| 字段               | 类型      | 描述                               |
+| ------------------ | --------- | ---------------------------------- |
+| id                 | bigint    | 主键                               |
+| start_time         | timestamp | 任务开始时间                       |
+| end_time           | timestamp | 任务结束时间                       |
+| notify_num         | int       | 通知数量                           |
+| notify_success_num | int       | 通知成功数量                       |
+| notify_fail_num    | int       | 通知失败数量                       |
+| error_message      | text      | 失败异常信息                       |
+| created_by         | bigint    | 创建人                             |
+| creation_time      | timestamp | 创建时间                           |
+| last_updated_by    | bigint    | 最后更信人                         |
+| last_update_time   | timestamp | 最后更新时间                       |
+| version            | bigint    | 版本号                             |
+| delete_flag        | tinyint   | 逻辑删除标志(0-未删除,1-已删除) |
+
+
+
+#### 开发参考
+
+* [两种优雅的获取当前登录用户ID的方式](https://blog.csdn.net/tomorrow9813/article/details/131736382)
+* [学会自己编写Mybatis插件(拦截器)实现自定义需求](https://juejin.cn/post/7220321558103097404#heading-3)
+* [Mybatis拦截器教程及几个实用自定义拦截器分享](https://juejin.cn/post/7242129949179248700#heading-5)
 
 
 
 
 
 
@@ -241,3 +295,23 @@ mysqld --standalone
 * [MYSQL8.0安装、配置、启动、登入与卸载详细步骤总结](https://blog.csdn.net/qq_51688022/article/details/137105751)
 * [MYSQL8.0安装、配置、启动、登入与卸载详细步骤总结](https://blog.csdn.net/qq_51688022/article/details/137105751)
 * [mysql服务没有响应控制功能](https://blog.csdn.net/m0_72160374/article/details/143462612)
 * [mysql服务没有响应控制功能](https://blog.csdn.net/m0_72160374/article/details/143462612)
 
 
+
+
+## IDEA设置
+
+
+
+### 类注释模板
+
+模板
+
+```java
+/**
+ * @author ${USER}
+ * @version 1.0.0
+ * @date ${DATE} ${TIME}
+ * @description TODO
+ */
+```
+
+参考:[IDEA 创建类注释模板](https://blog.csdn.net/GyaoG/article/details/120415660)

+ 5 - 17
pom.xml

@@ -16,15 +16,13 @@
     <version>1.0-SNAPSHOT</version>
     <version>1.0-SNAPSHOT</version>
 
 
     <properties>
     <properties>
-        <maven.compiler.source>17</maven.compiler.source>
-        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.source>21</maven.compiler.source>
+        <maven.compiler.target>21</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <java.version>17</java.version>
+        <java.version>21</java.version>
         <spring-cloud.version>2023.0.3</spring-cloud.version>
         <spring-cloud.version>2023.0.3</spring-cloud.version>
-<!--        <mybatis-mapper.version>5.0.0</mybatis-mapper.version>-->
         <jwt.version>4.4.0</jwt.version>
         <jwt.version>4.4.0</jwt.version>
-        <mybatis-springboot-starter.version>3.0.3</mybatis-springboot-starter.version>
-        <mapper-spring-boot-starter.version>5.0.1</mapper-spring-boot-starter.version>
+        <tk-mybatis.version>5.0.1</tk-mybatis.version>
     </properties>
     </properties>
 
 
     <dependencyManagement>
     <dependencyManagement>
@@ -83,20 +81,10 @@
             <artifactId>lombok</artifactId>
             <artifactId>lombok</artifactId>
             <optional>true</optional>
             <optional>true</optional>
         </dependency>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>tk.mybatis</groupId>-->
-<!--            <artifactId>mapper</artifactId>-->
-<!--            <version>${mybatis-mapper.version}</version>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>org.mybatis.spring.boot</groupId>-->
-<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
-<!--            <version>${mybatis-springboot-starter.version}</version>-->
-<!--        </dependency>-->
         <dependency>
         <dependency>
             <groupId>tk.mybatis</groupId>
             <groupId>tk.mybatis</groupId>
             <artifactId>mapper-spring-boot-starter</artifactId>
             <artifactId>mapper-spring-boot-starter</artifactId>
-            <version>${mapper-spring-boot-starter.version}</version>
+            <version>${tk-mybatis.version}</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>com.auth0</groupId>
             <groupId>com.auth0</groupId>

+ 9 - 5
src/main/java/com/punchsettle/server/atomic/entity/PunchIn.java

@@ -1,20 +1,24 @@
 package com.punchsettle.server.atomic.entity;
 package com.punchsettle.server.atomic.entity;
 
 
+import java.io.Serial;
+import java.io.Serializable;
+
 import com.punchsettle.server.common.entity.BaseEntity;
 import com.punchsettle.server.common.entity.BaseEntity;
+
 import jakarta.persistence.Column;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import jakarta.persistence.Table;
 import lombok.Data;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.EqualsAndHashCode;
 
 
-import java.io.Serial;
-import java.io.Serializable;
-
 /**
 /**
- * 打卡任务表
+ * @description 打卡任务表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
  */
  */
 @Data
 @Data
-@Table(name = "punch_in")
 @EqualsAndHashCode(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
+@Table(name = "punch_in")
 public class PunchIn extends BaseEntity implements Serializable {
 public class PunchIn extends BaseEntity implements Serializable {
 
 
     @Serial
     @Serial

+ 38 - 0
src/main/java/com/punchsettle/server/atomic/entity/PunchInRecord.java

@@ -0,0 +1,38 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @description 打卡任务记录表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "punch_in_record")
+public class PunchInRecord extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -7093764607676755235L;
+
+    /**
+     * 打卡任务表主键
+     */
+    @Column(name = "punch_in_id")
+    private Long punchInId;
+
+    /**
+     * 打卡日期
+     */
+    @Column(name = "punch_in_date")
+    private String punchInDate;
+}

+ 38 - 0
src/main/java/com/punchsettle/server/atomic/entity/PunchInRecordSettlementRela.java

@@ -0,0 +1,38 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @description 打卡任务记录与结算关联表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "punch_in_record_settlement_rela")
+public class PunchInRecordSettlementRela extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 7950526992192733109L;
+
+    /**
+     * 打卡任务记录表ID
+     */
+    @Column(name = "record_id")
+    private Long recordId;
+
+    /**
+     * 打卡任务结算表ID
+     */
+    @Column(name = "settlement_id")
+    private Long settlementId;
+}

+ 81 - 0
src/main/java/com/punchsettle/server/atomic/entity/PunchInSettlement.java

@@ -0,0 +1,81 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @description 打卡任务结算表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "punch_in_settlement")
+public class PunchInSettlement extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -3583266996949699066L;
+
+    /**
+     * 用户表主键
+     */
+    @Column(name = "user_id")
+    private Long userId;
+
+    /**
+     * 结算奖励数
+     */
+    @Column(name = "settle_reward_num")
+    private Integer settleRewardNum;
+
+    /**
+     * 结算前用户拥有的奖励数
+     */
+    @Column(name = "before_settle_reward_num")
+    private Integer beforeSettleRewardNum;
+
+    /**
+     * 结算后用户拥有的奖励数
+     */
+    @Column(name = "after_settle_reward_num")
+    private Integer afterSettleRewardNum;
+
+    /**
+     * 结算任务表id
+     */
+    @Column(name = "settlement_task_id")
+    private Long settlementTaskId;
+
+    /**
+     * 结算时间
+     */
+    @Column(name = "settlement_time")
+    private Timestamp settlementTime;
+
+    /**
+     * 通知表ID
+     */
+    @Column(name = "notify_id")
+    private Long notifyId;
+
+    /**
+     * 结算通知状态(fail-通知失败,success-成功通知,pending-待通知)
+     */
+    @Column(name = "notify_status")
+    private String notifyStatus;
+
+    /**
+     * 结算通知时间
+     */
+    @Column(name = "notify_time")
+    private Timestamp notifyTime;
+}

+ 67 - 0
src/main/java/com/punchsettle/server/atomic/entity/SettlementNotifyTask.java

@@ -0,0 +1,67 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 通知定时任务执行记录表
+ * @author tyuio
+ */
+/**
+ * @description 通知定时任务执行记录表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "settlement_notify_task")
+public class SettlementNotifyTask extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -5529226488225591121L;
+
+    /**
+     * 任务开始时间
+     */
+    @Column(name = "start_time")
+    private Timestamp startTime;
+
+    /**
+     * 任务结束时间
+     */
+    @Column(name = "end_time")
+    private Timestamp endTime;
+
+    /**
+     * 任务状态(success-成功,fail-失败,processing-处理中)
+     */
+    @Column(name = "task_status")
+    private String taskStatus;
+
+    /**
+     * 通知数量
+     */
+    @Column(name = "notify_num")
+    private Integer notifyNum;
+
+    /**
+     * 通知成功数量
+     */
+    @Column(name = "notify_success_num")
+    private Integer notifySuccessNum;
+
+    /**
+     * 通知失败数量
+     */
+    @Column(name = "notify_fail_num")
+    private Integer notifyFailNum;
+}

+ 63 - 0
src/main/java/com/punchsettle/server/atomic/entity/SettlementTask.java

@@ -0,0 +1,63 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @description 奖励结算定时任务执行记录表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "settlement_task")
+public class SettlementTask extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 4359906154365259984L;
+
+    /**
+     * 结算日期
+     */
+    @Column(name = "settle_date")
+    private String settleDate;
+
+    /**
+     * 任务开始时间
+     */
+    @Column(name = "start_time")
+    private Timestamp startTime;
+
+    /**
+     * 任务结束时间
+     */
+    @Column(name = "end_time")
+    private Timestamp endTime;
+
+    /**
+     * 待处理结算数量
+     */
+    @Column(name = "processed_num")
+    private Integer processedNum;
+
+    /**
+     * 处理已结算数量
+     */
+    @Column(name = "processed_settle_num")
+    private Integer processedSettleNum;
+
+    /**
+     * 处理没结算数量
+     */
+    @Column(name = "processed_unsettle_num")
+    private Integer processedUnsettleNum;
+}

+ 44 - 0
src/main/java/com/punchsettle/server/atomic/entity/User.java

@@ -0,0 +1,44 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @description 用户表 实体
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "user")
+public class User extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -7534708835316500183L;
+
+    /**
+     * 微信id
+     */
+    @Column(name = "open_id")
+    private String openId;
+
+    /**
+     * 微信昵称
+     */
+    @Column(name = "nickname")
+    private String nickname;
+
+    /**
+     * 微信头像url
+     */
+    @Column(name = "avatar")
+    private String avatar;
+}

+ 57 - 0
src/main/java/com/punchsettle/server/atomic/entity/UserClaimRewardRecord.java

@@ -0,0 +1,57 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 领取奖励记录表
+ * @date 2024/11/25 20:44
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "user_claim_reward_record")
+public class UserClaimRewardRecord extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 3347775963495102677L;
+
+    /**
+     * 用户表主键
+     */
+    @Column(name = "user_id")
+    private Long userId;
+
+    /**
+     * 本次领取奖励数
+     */
+    @Column(name = "claim_reward_num")
+    private Integer claimRewardNum;
+
+    /**
+     * 领取奖励时间
+     */
+    @Column(name = "claim_reward_time")
+    private Timestamp claimRewardTime;
+
+    /**
+     * 领取前用户拥有的奖励数
+     */
+    @Column(name = "before_claim_reward_num")
+    private Integer beforeClaimRewardNum;
+
+    /**
+     * 领取后用户拥有的奖励数
+     */
+    @Column(name = "after_claim_reward_num")
+    private Integer afterClaimRewardNum;
+}

+ 50 - 0
src/main/java/com/punchsettle/server/atomic/entity/UserReward.java

@@ -0,0 +1,50 @@
+package com.punchsettle.server.atomic.entity;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户奖励数据表
+ * @date 2024/11/25 20:39
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "user_reward")
+public class UserReward extends BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -4590939776485091913L;
+
+    /**
+     * 用户表主键
+     */
+    @Column(name = "user_id")
+    private Long userId;
+
+    /**
+     * 总奖励数
+     */
+    @Column(name = "total_reward_num")
+    private Integer totalRewardNum;
+
+    /**
+     * 未领取奖励数
+     */
+    @Column(name = "unclaimed_reward_num")
+    private Integer unclaimedRewardNum;
+
+    /**
+     * 已领取奖励数
+     */
+    @Column(name = "claimed_reward_num")
+    private Integer claimedRewardNum;
+}

+ 6 - 4
src/main/java/com/punchsettle/server/atomic/mapper/PunchInMapper.java

@@ -1,12 +1,14 @@
 package com.punchsettle.server.atomic.mapper;
 package com.punchsettle.server.atomic.mapper;
 
 
 import com.punchsettle.server.atomic.entity.PunchIn;
 import com.punchsettle.server.atomic.entity.PunchIn;
+
 import tk.mybatis.mapper.common.Mapper;
 import tk.mybatis.mapper.common.Mapper;
-import tk.mybatis.mapper.common.MySqlMapper;
 
 
 /**
 /**
- * 打卡任务表 Mapper
+ * @description 打卡任务表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
  */
  */
-//@Mapper
-public interface PunchInMapper extends Mapper<PunchIn>, MySqlMapper<PunchIn> {
+public interface PunchInMapper extends Mapper<PunchIn> {
 }
 }

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/PunchInRecordMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.PunchInRecord;
+
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @description 打卡任务记录表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+public interface PunchInRecordMapper extends Mapper<PunchInRecord> {
+}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/PunchInRecordSettlementRelaMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela;
+
+import tk.mybatis.mapper.additional.insert.InsertListMapper;
+
+/**
+ * @description 打卡任务记录与结算关联表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+public interface PunchInRecordSettlementRelaMapper extends InsertListMapper<PunchInRecordSettlementRela> {
+}

+ 15 - 0
src/main/java/com/punchsettle/server/atomic/mapper/PunchInSettlementMapper.java

@@ -0,0 +1,15 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.PunchInSettlement;
+
+import tk.mybatis.mapper.additional.insert.InsertListMapper;
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @description 打卡任务结算表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+public interface PunchInSettlementMapper extends Mapper<PunchInSettlement>, InsertListMapper<PunchInSettlement> {
+}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/SettlementNotifyTaskMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.SettlementNotifyTask;
+
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @description 通知定时任务执行记录表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+public interface SettlementNotifyTaskMapper extends Mapper<SettlementNotifyTask> {
+}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/SettlementTaskMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.SettlementTask;
+
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @description 奖励结算定时任务执行记录表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+public interface SettlementTaskMapper extends Mapper<SettlementTask> {
+}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/UserClaimRewardRecordMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.UserClaimRewardRecord;
+
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 领取奖励记录表
+ * @date 2024/11/25 20:49
+ */
+public interface UserClaimRewardRecordMapper extends Mapper<UserClaimRewardRecord> {
+}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/UserMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.User;
+
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @description 用户表 mapper
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
+ */
+public interface UserMapper extends Mapper<User> {
+}

+ 15 - 0
src/main/java/com/punchsettle/server/atomic/mapper/UserRewardMapper.java

@@ -0,0 +1,15 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.UserReward;
+
+import tk.mybatis.mapper.additional.update.batch.BatchUpdateSelectiveMapper;
+import tk.mybatis.mapper.common.Mapper;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户奖励数据表 mapper
+ * @date 2024/11/25 20:49
+ */
+public interface UserRewardMapper extends Mapper<UserReward>, BatchUpdateSelectiveMapper<UserReward> {
+}

+ 28 - 0
src/main/java/com/punchsettle/server/atomic/service/IPunchInRecordService.java

@@ -0,0 +1,28 @@
+package com.punchsettle.server.atomic.service;
+
+import java.util.List;
+
+import com.punchsettle.server.atomic.entity.PunchInRecord;
+import com.punchsettle.server.dto.PunchInRecordQuery;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务记录表 service
+ * @date 2024/11/25 15:33
+ */
+public interface IPunchInRecordService {
+
+    /**
+     * 新增打卡记录
+     * @param record
+     */
+    void insert(PunchInRecord record);
+
+    /**
+     * 根据查询条件查询打卡记录
+     * @param query
+     * @return
+     */
+    List<PunchInRecord> listByCondition(PunchInRecordQuery query);
+}

+ 20 - 0
src/main/java/com/punchsettle/server/atomic/service/IPunchInRecordSettlementRelaService.java

@@ -0,0 +1,20 @@
+package com.punchsettle.server.atomic.service;
+
+import java.util.List;
+
+import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务记录与结算关联表
+ * @date 2024/11/26 12:53
+ */
+public interface IPunchInRecordSettlementRelaService {
+
+    /**
+     * 批量新增
+     * @param punchInRecordSettlementRelas
+     */
+    void batchInsert(List<PunchInRecordSettlementRela> punchInRecordSettlementRelas);
+}

+ 47 - 0
src/main/java/com/punchsettle/server/atomic/service/IPunchInService.java

@@ -0,0 +1,47 @@
+package com.punchsettle.server.atomic.service;
+
+import java.util.List;
+
+import com.punchsettle.server.atomic.entity.PunchIn;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡结算任务表 service
+ * @date 2024/11/25 15:04
+ */
+public interface IPunchInService {
+
+    /**
+     * 根据创建人查询所有的打卡结算任务数据
+     * @param createdBy
+     * @return
+     */
+    List<PunchIn> listByCreatedBy(Long createdBy);
+
+    /**
+     * 根据主键查询打卡任务
+     * @param id
+     * @return
+     */
+    PunchIn getById(Long id);
+
+    /**
+     * 根据创建人查询所有的打卡结算任务数据
+     * @param userIds 创建人id
+     * @return
+     */
+    List<PunchIn> listByCreatedBy(List<Long> userIds);
+
+    /**
+     * 新增或更新打卡结算任务
+     * @param punchIn
+     */
+    void insertOrUpdate(PunchIn punchIn);
+
+    /**
+     * 根据主键删除打卡结算任务
+     * @param punchInId
+     */
+    void delete(Long punchInId);
+}

+ 20 - 0
src/main/java/com/punchsettle/server/atomic/service/IPunchInSettlementService.java

@@ -0,0 +1,20 @@
+package com.punchsettle.server.atomic.service;
+
+import java.util.List;
+
+import com.punchsettle.server.atomic.entity.PunchInSettlement;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务结算表
+ * @date 2024/11/26 12:35
+ */
+public interface IPunchInSettlementService {
+
+    /**
+     * 批量新增
+     * @param punchInSettlements
+     */
+    void batchInsert(List<PunchInSettlement> punchInSettlements);
+}

+ 24 - 0
src/main/java/com/punchsettle/server/atomic/service/ISettlementTaskService.java

@@ -0,0 +1,24 @@
+package com.punchsettle.server.atomic.service;
+
+import com.punchsettle.server.atomic.entity.SettlementTask;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 奖励结算定时任务执行记录表
+ * @date 2024/11/26 11:53
+ */
+public interface ISettlementTaskService {
+
+    /**
+     * 新增
+     * @param task
+     */
+    void insert(SettlementTask task);
+
+    /**
+     * 更新
+     * @param task
+     */
+    void update(SettlementTask task);
+}

+ 18 - 0
src/main/java/com/punchsettle/server/atomic/service/IUserClaimRewardRecordService.java

@@ -0,0 +1,18 @@
+package com.punchsettle.server.atomic.service;
+
+import com.punchsettle.server.atomic.entity.UserClaimRewardRecord;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 领取奖励记录表 service
+ * @date 2024/11/25 22:13
+ */
+public interface IUserClaimRewardRecordService {
+
+    /**
+     * 新增领取奖励记录
+     * @param record
+     */
+    void insert(UserClaimRewardRecord record);
+}

+ 40 - 0
src/main/java/com/punchsettle/server/atomic/service/IUserRewardService.java

@@ -0,0 +1,40 @@
+package com.punchsettle.server.atomic.service;
+
+import java.util.List;
+
+import com.punchsettle.server.atomic.entity.UserReward;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户奖励数据表 service
+ * @date 2024/11/25 22:10
+ */
+public interface IUserRewardService {
+
+    /**
+     * 根据当前用户获取用户奖励数
+     * @param currentUserId 当前用户id
+     * @return
+     */
+    UserReward getByUserId(Long currentUserId);
+
+    /**
+     * 更新用户奖励数
+     * @param userReward
+     */
+    void updateReward(UserReward userReward);
+
+    /**
+     * 根据用户id列表查询用户奖励列表
+     * @param userIds
+     * @return
+     */
+    List<UserReward> listByUserIds(List<Long> userIds);
+
+    /**
+     * 批量更新用户奖励数
+     * @param userRewards
+     */
+    void batchUpdateUserReward(List<UserReward> userRewards);
+}

+ 34 - 0
src/main/java/com/punchsettle/server/atomic/service/IUserService.java

@@ -0,0 +1,34 @@
+package com.punchsettle.server.atomic.service;
+
+import java.util.List;
+
+import com.punchsettle.server.atomic.entity.User;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户表 service
+ * @date 2024/11/25 12:30
+ */
+public interface IUserService {
+
+    /**
+     * 根据ID查找用户
+     * @param id
+     * @return
+     */
+    User getById(Long id);
+
+    /**
+     * 获取ID获取用户,不存在时新增
+     * @param openId 微信openid
+     * @return
+     */
+    User getAndAdd(String openId);
+
+    /**
+     * 查询所有用户
+     * @return
+     */
+    List<User> list();
+}

+ 46 - 3
src/main/java/com/punchsettle/server/atomic/service/impl/PunchInRecordServiceImpl.java

@@ -1,11 +1,54 @@
 package com.punchsettle.server.atomic.service.impl;
 package com.punchsettle.server.atomic.service.impl;
 
 
-import com.punchsettle.server.atomic.service.PunchInRecordService;
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.entity.PunchInRecord;
+import com.punchsettle.server.atomic.mapper.PunchInRecordMapper;
+import com.punchsettle.server.atomic.service.IPunchInRecordService;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.dto.PunchInRecordQuery;
+
+import io.micrometer.common.util.StringUtils;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
 
 
 /**
 /**
- * 打卡任务记录表 service
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务记录表 service
+ * @date 2024/11/25 15:34
  */
  */
 @Service
 @Service
-public class PunchInRecordServiceImpl implements PunchInRecordService {
+public class PunchInRecordServiceImpl implements IPunchInRecordService {
+
+    @Autowired
+    private PunchInRecordMapper punchInRecordMapper;
+
+    @Override
+    public void insert(PunchInRecord record) {
+        Assert.isNull(record);
+        punchInRecordMapper.insertSelective(record);
+    }
+
+    @Override
+    public List<PunchInRecord> listByCondition(PunchInRecordQuery query) {
+        if (Objects.isNull(query)) {
+            return List.of();
+        }
+
+        Weekend<PunchInRecord> weekend = Weekend.of(PunchInRecord.class);
+        WeekendCriteria<PunchInRecord, Object> criteria = weekend.weekendCriteria();
+        if (StringUtils.isNotBlank(query.getStartDate()) && StringUtils.isNotBlank(query.getEndDate())) {
+            criteria.andBetween(PunchInRecord::getPunchInDate, query.getStartDate(), query.getEndDate());
+        }
+        if (!CollectionUtils.isEmpty(query.getPunchInIds())) {
+            criteria.andIn(PunchInRecord::getPunchInId, query.getPunchInIds());
+        }
+        return punchInRecordMapper.selectByExample(weekend);
+    }
 }
 }

+ 33 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PunchInRecordSettlementRelaServiceImpl.java

@@ -0,0 +1,33 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela;
+import com.punchsettle.server.atomic.mapper.PunchInRecordSettlementRelaMapper;
+import com.punchsettle.server.atomic.service.IPunchInRecordSettlementRelaService;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务记录与结算关联表
+ * @date 2024/11/26 12:54
+ */
+@Service
+public class PunchInRecordSettlementRelaServiceImpl implements IPunchInRecordSettlementRelaService {
+
+    @Autowired
+    private PunchInRecordSettlementRelaMapper punchInRecordSettlementRelaMapper;
+
+    @Override
+    public void batchInsert(List<PunchInRecordSettlementRela> punchInRecordSettlementRelas) {
+        if (CollectionUtils.isEmpty(punchInRecordSettlementRelas)) {
+            return;
+        }
+
+        punchInRecordSettlementRelaMapper.insertList(punchInRecordSettlementRelas);
+    }
+}

+ 76 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PunchInServiceImpl.java

@@ -0,0 +1,76 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.entity.PunchIn;
+import com.punchsettle.server.atomic.mapper.PunchInMapper;
+import com.punchsettle.server.atomic.service.IPunchInService;
+import com.punchsettle.server.common.utils.Assert;
+
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务表 service
+ * @date 2024/11/25 15:07
+ */
+@Service
+public class PunchInServiceImpl implements IPunchInService {
+
+    @Autowired
+    private PunchInMapper punchInMapper;
+
+    @Override
+    public List<PunchIn> listByCreatedBy(Long createdBy) {
+        if (Objects.isNull(createdBy)) {
+            return List.of();
+        }
+
+        PunchIn query = new PunchIn();
+        query.setCreatedBy(createdBy);
+        return punchInMapper.select(query);
+    }
+
+    @Override
+    public PunchIn getById(Long id) {
+        if (Objects.isNull(id)) {
+            return null;
+        }
+        return punchInMapper.selectByPrimaryKey(id);
+    }
+
+    @Override
+    public List<PunchIn> listByCreatedBy(List<Long> userIds) {
+        if (CollectionUtils.isEmpty(userIds)) {
+            return List.of();
+        }
+
+        Weekend<PunchIn> punchInWeekend = Weekend.of(PunchIn.class);
+        WeekendCriteria<PunchIn, Object> criteria = punchInWeekend.weekendCriteria();
+        criteria.andIn(PunchIn::getCreatedBy, userIds);
+        return punchInMapper.selectByExample(punchInWeekend);
+    }
+
+    @Override
+    public void insertOrUpdate(PunchIn punchIn) {
+        Assert.isNull(punchIn);
+        if (Objects.isNull(punchIn.getId())) {
+            punchInMapper.insertSelective(punchIn);
+        } else {
+            punchInMapper.updateByPrimaryKeySelective(punchIn);
+        }
+    }
+
+    @Override
+    public void delete(Long punchInId) {
+        Assert.isNull(punchInId);
+        punchInMapper.deleteByPrimaryKey(punchInId);
+    }
+}

+ 30 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PunchInSettlementServiceImpl.java

@@ -0,0 +1,30 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.punchsettle.server.atomic.entity.PunchInSettlement;
+import com.punchsettle.server.atomic.mapper.PunchInSettlementMapper;
+import com.punchsettle.server.atomic.service.IPunchInSettlementService;
+import com.punchsettle.server.common.utils.Assert;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务结算表
+ * @date 2024/11/26 12:39
+ */
+@Service
+public class PunchInSettlementServiceImpl implements IPunchInSettlementService {
+
+    @Autowired
+    private PunchInSettlementMapper punchInSettlementMapper;
+
+    @Override
+    public void batchInsert(List<PunchInSettlement> punchInSettlements) {
+        Assert.notEmpty(punchInSettlements);
+        punchInSettlementMapper.insertList(punchInSettlements);
+    }
+}

+ 34 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/SettlementTaskServiceImpl.java

@@ -0,0 +1,34 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.punchsettle.server.atomic.entity.SettlementTask;
+import com.punchsettle.server.atomic.mapper.SettlementTaskMapper;
+import com.punchsettle.server.atomic.service.ISettlementTaskService;
+import com.punchsettle.server.common.utils.Assert;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 奖励结算定时任务执行记录表
+ * @date 2024/11/26 11:55
+ */
+@Service
+public class SettlementTaskServiceImpl implements ISettlementTaskService {
+
+    @Autowired
+    private SettlementTaskMapper settlementTaskMapper;
+
+    @Override
+    public void insert(SettlementTask task) {
+        Assert.isNull(task);
+        settlementTaskMapper.insertSelective(task);
+    }
+
+    @Override
+    public void update(SettlementTask task) {
+        Assert.isNull(task);
+        settlementTaskMapper.updateByPrimaryKeySelective(task);
+    }
+}

+ 28 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/UserClaimRewardRecordServiceImpl.java

@@ -0,0 +1,28 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.punchsettle.server.atomic.entity.UserClaimRewardRecord;
+import com.punchsettle.server.atomic.mapper.UserClaimRewardRecordMapper;
+import com.punchsettle.server.atomic.service.IUserClaimRewardRecordService;
+import com.punchsettle.server.common.utils.Assert;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 领取奖励记录表 service
+ * @date 2024/11/25 22:18
+ */
+@Service
+public class UserClaimRewardRecordServiceImpl implements IUserClaimRewardRecordService {
+
+    @Autowired
+    private UserClaimRewardRecordMapper userClaimRewardRecordMapper;
+
+    @Override
+    public void insert(UserClaimRewardRecord record) {
+        Assert.isNull(record);
+        userClaimRewardRecordMapper.insertSelective(record);
+    }
+}

+ 69 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/UserRewardServiceImpl.java

@@ -0,0 +1,69 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.entity.UserReward;
+import com.punchsettle.server.atomic.mapper.UserRewardMapper;
+import com.punchsettle.server.atomic.service.IUserRewardService;
+import com.punchsettle.server.common.utils.Assert;
+
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户奖励数据表 service
+ * @date 2024/11/25 22:14
+ */
+@Service
+public class UserRewardServiceImpl implements IUserRewardService {
+
+    @Autowired
+    private UserRewardMapper userRewardMapper;
+
+    @Override
+    public UserReward getByUserId(Long currentUserId) {
+        if (Objects.isNull(currentUserId)) {
+            return null;
+        }
+
+        UserReward userReward = new UserReward();
+        userReward.setUserId(currentUserId);
+        return userRewardMapper.selectOne(userReward);
+    }
+
+    @Override
+    public void updateReward(UserReward userReward) {
+        Assert.isNull(userReward);
+
+        if (Objects.isNull(userReward)) {
+            userRewardMapper.insertSelective(userReward);
+        } else {
+            userRewardMapper.updateByPrimaryKeySelective(userReward);
+        }
+    }
+
+    @Override
+    public List<UserReward> listByUserIds(List<Long> userIds) {
+        if(CollectionUtils.isEmpty(userIds)) {
+            return List.of();
+        }
+
+        Weekend<UserReward> weekend = Weekend.of(UserReward.class);
+        WeekendCriteria<UserReward, Object> criteria = weekend.weekendCriteria();
+        criteria.andIn(UserReward::getUserId, userIds);
+        return userRewardMapper.selectByExample(weekend);
+    }
+
+    @Override
+    public void batchUpdateUserReward(List<UserReward> userRewards) {
+        Assert.notEmpty(userRewards);
+        userRewardMapper.batchUpdateSelective(userRewards);
+    }
+}

+ 50 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/UserServiceImpl.java

@@ -0,0 +1,50 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.punchsettle.server.atomic.entity.User;
+import com.punchsettle.server.atomic.mapper.UserMapper;
+import com.punchsettle.server.atomic.service.IUserService;
+
+import io.micrometer.common.util.StringUtils;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户表 service
+ * @date 2024/11/25 12:30
+ */
+@Service
+public class UserServiceImpl implements IUserService {
+
+    @Autowired
+    private UserMapper userMapper;
+
+    @Override
+    public User getById(Long id) {
+        if (Objects.isNull(id)) {
+            return null;
+        }
+        return userMapper.selectByPrimaryKey(id);
+    }
+
+    @Override
+    public User getAndAdd(String openId) {
+        if (StringUtils.isBlank(openId)) {
+            return null;
+        }
+
+        User queryUser = new User();
+        queryUser.setOpenId(openId);
+        return userMapper.selectOne(queryUser);
+    }
+
+    @Override
+    public List<User> list() {
+        return userMapper.selectAll();
+    }
+}

+ 2 - 2
src/main/java/com/punchsettle/server/common/converter/enums/IntegerToEnumConverter.java

@@ -1,10 +1,10 @@
 package com.punchsettle.server.common.converter.enums;
 package com.punchsettle.server.common.converter.enums;
 
 
-import org.springframework.core.convert.converter.Converter;
-
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
 
 
+import org.springframework.core.convert.converter.Converter;
+
 /**
 /**
  * 转换器 数值转换为枚举
  * 转换器 数值转换为枚举
  *
  *

+ 3 - 3
src/main/java/com/punchsettle/server/common/converter/enums/IntegerToEnumConverterFactory.java

@@ -1,11 +1,11 @@
 package com.punchsettle.server.common.converter.enums;
 package com.punchsettle.server.common.converter.enums;
 
 
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.core.convert.converter.ConverterFactory;
-
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
 
 
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.convert.converter.ConverterFactory;
+
 public class IntegerToEnumConverterFactory implements ConverterFactory<Integer, IJsonEnum> {
 public class IntegerToEnumConverterFactory implements ConverterFactory<Integer, IJsonEnum> {
 
 
     private static final Map<Class, Converter> CONVERTERS = new HashMap<>();
     private static final Map<Class, Converter> CONVERTERS = new HashMap<>();

+ 5 - 4
src/main/java/com/punchsettle/server/common/dto/JsonResponse.java

@@ -1,14 +1,15 @@
 package com.punchsettle.server.common.dto;
 package com.punchsettle.server.common.dto;
 
 
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.punchsettle.server.common.constant.ResponseCodeEnum;
 import com.punchsettle.server.common.constant.ResponseCodeEnum;
+
 import lombok.Data;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.EqualsAndHashCode;
 
 
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-
 /**
 /**
  * json 统一响应体
  * json 统一响应体
  *
  *

+ 9 - 7
src/main/java/com/punchsettle/server/common/entity/BaseEntity.java

@@ -1,15 +1,18 @@
 package com.punchsettle.server.common.entity;
 package com.punchsettle.server.common.entity;
 
 
+import java.sql.Timestamp;
+
 import jakarta.persistence.Column;
 import jakarta.persistence.Column;
 import jakarta.persistence.Id;
 import jakarta.persistence.Id;
 import lombok.Data;
 import lombok.Data;
+import tk.mybatis.mapper.annotation.KeySql;
 import tk.mybatis.mapper.annotation.LogicDelete;
 import tk.mybatis.mapper.annotation.LogicDelete;
-import tk.mybatis.mapper.annotation.Version;
-
-import java.sql.Timestamp;
 
 
 /**
 /**
- * 实体类基础属性
+ * @description 实体类基类(6个通用审计字段)
+ * @version 1.0.0
+ * @date 2024/11/25 10:57
+ * @author tyuio
  */
  */
 @Data
 @Data
 public class BaseEntity {
 public class BaseEntity {
@@ -18,6 +21,7 @@ public class BaseEntity {
      * 主键
      * 主键
      */
      */
     @Id
     @Id
+    @KeySql(useGeneratedKeys = true)
     @Column(name = "id")
     @Column(name = "id")
     private Long id;
     private Long id;
 
 
@@ -48,7 +52,6 @@ public class BaseEntity {
     /**
     /**
      * 版本号
      * 版本号
      */
      */
-    @Version
     @Column(name = "version")
     @Column(name = "version")
     private Integer version;
     private Integer version;
 
 
@@ -56,7 +59,6 @@ public class BaseEntity {
      * 逻辑删除标志(0-未删除,1-已删除)
      * 逻辑删除标志(0-未删除,1-已删除)
      */
      */
     @LogicDelete
     @LogicDelete
-    @Column(name = "delete_flag")
-    private String deleteFlag;
+    private Boolean deleteFlag;
 
 
 }
 }

+ 72 - 0
src/main/java/com/punchsettle/server/common/utils/Assert.java

@@ -0,0 +1,72 @@
+package com.punchsettle.server.common.utils;
+
+import java.util.Collection;
+import java.util.Objects;
+
+import com.punchsettle.server.common.exception.BusinessException;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 断言工具类
+ * @date 2024/11/26 19:43
+ */
+public class Assert {
+
+    /**
+     * 判断对象是否为空
+     * @param object 待判断对象
+     * @param errorMsg 异常提示信息
+     * @throws IllegalArgumentException
+     */
+    public static void isNull(Object object, String errorMsg) throws IllegalArgumentException {
+        if (Objects.isNull(object)) {
+            throw new IllegalArgumentException(errorMsg);
+        }
+    }
+
+    /**
+     * 判断对象是否为空
+     * @param object 待判断对象
+     * @throws IllegalArgumentException
+     */
+    public static void isNull(Object object) throws IllegalArgumentException {
+        isNull(object, "传入的对象参数不能为空");
+    }
+
+    /**
+     * 判断对象是否为空
+     * @param object 待判断对象
+     * @param errorMsg 异常提示信息
+     * @throws BusinessException
+     */
+    public static void isNullInBusiness(Object object, String errorMsg) throws BusinessException {
+        if (Objects.isNull(object)) {
+            throw new BusinessException(errorMsg);
+        }
+    }
+
+    /**
+     * 判断集合是否为空
+     * @param collection 待判断对象
+     * @param errorMsg 异常提示信息
+     * @return
+     * @param <T>
+     * @throws IllegalArgumentException
+     */
+    public static <T> void notEmpty(Collection<T> collection, String errorMsg) throws IllegalArgumentException {
+        if (collection == null || collection.isEmpty()) {
+            throw new IllegalArgumentException(errorMsg);
+        }
+    }
+
+    /**
+     * 判断集合是否为空
+     * @param collection 待判断对象
+     * @param <T>
+     * @throws IllegalArgumentException
+     */
+    public static <T> void notEmpty(Collection<T> collection) throws IllegalArgumentException {
+        notEmpty(collection, "传入的集合参数不能为空");
+    }
+}

+ 10 - 0
src/main/java/com/punchsettle/server/common/valid/Delete.java

@@ -0,0 +1,10 @@
+package com.punchsettle.server.common.valid;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 删除 校验器分组
+ * @date 2024/11/26 15:23
+ */
+public interface Delete {
+}

+ 10 - 0
src/main/java/com/punchsettle/server/common/valid/DoSomething.java

@@ -0,0 +1,10 @@
+package com.punchsettle.server.common.valid;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 做某一操作 校验器分组
+ * @date 2024/11/26 15:47
+ */
+public interface DoSomething {
+}

+ 10 - 0
src/main/java/com/punchsettle/server/common/valid/Query.java

@@ -0,0 +1,10 @@
+package com.punchsettle.server.common.valid;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 查询 校验器分组
+ * @date 2024/11/26 15:21
+ */
+public interface Query {
+}

+ 10 - 0
src/main/java/com/punchsettle/server/common/valid/Save.java

@@ -0,0 +1,10 @@
+package com.punchsettle.server.common.valid;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 新增 校验器分组
+ * @date 2024/11/26 15:22
+ */
+public interface Save {
+}

+ 10 - 0
src/main/java/com/punchsettle/server/common/valid/Update.java

@@ -0,0 +1,10 @@
+package com.punchsettle.server.common.valid;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 更新 校验器分组
+ * @date 2024/11/26 15:22
+ */
+public interface Update {
+}

+ 36 - 0
src/main/java/com/punchsettle/server/constant/PunchInStatusEnum.java

@@ -0,0 +1,36 @@
+package com.punchsettle.server.constant;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.Getter;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡状态 枚举
+ * @date 2024/11/26 21:59
+ */
+@Getter
+public enum PunchInStatusEnum {
+
+    UNCREATED("未创建打卡任务", "uncreated"),
+    PUNCH_IN("已打卡", "punchIn"),
+    UN_PUNCH_IN("没打卡", "unPunchIn"),
+    TODAY_UNKNOWN("当天打卡状态未知", "todayUnknown"),
+    FUTURE_TIME("未到打卡时间", "futureTime");
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 值
+     */
+    @JsonValue
+    private String value;
+
+    PunchInStatusEnum(String name, String value) {
+        this.name = name;
+        this.value = value;
+    }
+}

+ 39 - 5
src/main/java/com/punchsettle/server/core/aop/GlobalExceptionHandler.java

@@ -1,14 +1,21 @@
 package com.punchsettle.server.core.aop;
 package com.punchsettle.server.core.aop;
 
 
-import com.punchsettle.server.common.dto.JsonResponse;
-import com.punchsettle.server.common.exception.BusinessException;
-import com.punchsettle.server.common.exception.LoginException;
-import lombok.extern.slf4j.Slf4j;
+import java.util.List;
+import java.util.stream.Collectors;
+
 import org.springframework.http.HttpStatus;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.http.ResponseEntity;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 
 
+import com.punchsettle.server.common.dto.JsonResponse;
+import com.punchsettle.server.common.exception.BusinessException;
+import com.punchsettle.server.common.exception.LoginException;
+
+import lombok.extern.slf4j.Slf4j;
+
 /**
 /**
  * 全局异常处理
  * 全局异常处理
  */
  */
@@ -28,8 +35,35 @@ public class GlobalExceptionHandler {
         return JsonResponse.fail(e.getMessage());
         return JsonResponse.fail(e.getMessage());
     }
     }
 
 
+    /**
+     * 登录异常处理
+     * @param e
+     * @return
+     */
     @ExceptionHandler(LoginException.class)
     @ExceptionHandler(LoginException.class)
-    public ResponseEntity<Object> loginExceptionHandler(Exception e) {
+    public ResponseEntity<Object> loginExceptionHandler(LoginException e) {
         return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(JsonResponse.fail(e.getMessage()));
         return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(JsonResponse.fail(e.getMessage()));
     }
     }
+
+    /**
+     * 方法参数校验异常处理
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public JsonResponse methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
+        List<ObjectError> allErrors = e.getAllErrors();
+        String errorMsg = allErrors.stream().map(error -> error.getDefaultMessage())
+                .collect(Collectors.joining(";"));
+        return JsonResponse.fail(String.format("参数错误:%s", errorMsg));
+    }
+
+    /**
+     * 全局异常处理
+     */
+    @ExceptionHandler(Exception.class)
+    public JsonResponse exceptionHandler(Exception e) {
+        log.error(e.getMessage(), e);
+        return JsonResponse.fail("系统异常,请稍后再试");
+    }
 }
 }

+ 5 - 4
src/main/java/com/punchsettle/server/core/aop/ResponseControllerAdvice.java

@@ -1,9 +1,5 @@
 package com.punchsettle.server.core.aop;
 package com.punchsettle.server.core.aop;
 
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.punchsettle.server.common.annotation.IgnoreResponseWrapper;
-import com.punchsettle.server.common.dto.JsonResponse;
 import org.springframework.core.MethodParameter;
 import org.springframework.core.MethodParameter;
 import org.springframework.http.MediaType;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.http.ResponseEntity;
@@ -13,6 +9,11 @@ import org.springframework.http.server.ServerHttpResponse;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.punchsettle.server.common.annotation.IgnoreResponseWrapper;
+import com.punchsettle.server.common.dto.JsonResponse;
+
 /**
 /**
  * 接口返回统一处理
  * 接口返回统一处理
  */
  */

+ 4 - 3
src/main/java/com/punchsettle/server/core/aop/WebOperateLogAspect.java

@@ -1,7 +1,7 @@
 package com.punchsettle.server.core.aop;
 package com.punchsettle.server.core.aop;
 
 
-import jakarta.servlet.http.HttpServletRequest;
-import lombok.extern.slf4j.Slf4j;
+import java.util.Arrays;
+
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Aspect;
@@ -11,7 +11,8 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 
 
-import java.util.Arrays;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.extern.slf4j.Slf4j;
 
 
 @Slf4j
 @Slf4j
 @Aspect
 @Aspect

+ 2 - 1
src/main/java/com/punchsettle/server/core/config/BizConfig.java

@@ -1,9 +1,10 @@
 package com.punchsettle.server.core.config;
 package com.punchsettle.server.core.config;
 
 
-import lombok.Getter;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
 
 
+import lombok.Getter;
+
 @Getter
 @Getter
 @Configuration
 @Configuration
 public class BizConfig {
 public class BizConfig {

+ 6 - 5
src/main/java/com/punchsettle/server/core/config/FeignConfig.java

@@ -1,8 +1,8 @@
 package com.punchsettle.server.core.config;
 package com.punchsettle.server.core.config;
 
 
-import feign.Logger;
-import feign.RequestInterceptor;
-import feign.codec.Decoder;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.springframework.beans.factory.ObjectFactory;
 import org.springframework.beans.factory.ObjectFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
 import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
@@ -12,8 +12,9 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.http.MediaType;
 import org.springframework.http.MediaType;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 
 
-import java.util.ArrayList;
-import java.util.List;
+import feign.Logger;
+import feign.RequestInterceptor;
+import feign.codec.Decoder;
 
 
 /**
 /**
  * @className FeignConfig
  * @className FeignConfig

+ 19 - 1
src/main/java/com/punchsettle/server/core/config/TkMyBatisConfig.java

@@ -1,6 +1,11 @@
 package com.punchsettle.server.core.config;
 package com.punchsettle.server.core.config;
 
 
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
+
+import com.punchsettle.server.core.interceptor.MybatisAuditDataInterceptor;
+
+import tk.mybatis.mapper.autoconfigure.ConfigurationCustomizer;
 import tk.mybatis.spring.annotation.MapperScan;
 import tk.mybatis.spring.annotation.MapperScan;
 
 
 /**
 /**
@@ -8,4 +13,17 @@ import tk.mybatis.spring.annotation.MapperScan;
  */
  */
 @Configuration
 @Configuration
 @MapperScan(basePackages = "com.punchsettle.server.atomic.mapper")
 @MapperScan(basePackages = "com.punchsettle.server.atomic.mapper")
-public class TkMyBatisConfig {}
+public class MyBatisConfig {
+
+    @Bean
+    public ConfigurationCustomizer configurationCustomizer() {
+        // 添加审计数据插件
+        return new ConfigurationCustomizer() {
+            @Override
+            public void customize(org.apache.ibatis.session.Configuration configuration) {
+                MybatisAuditDataInterceptor auditDataInterceptor = new MybatisAuditDataInterceptor();
+                configuration.addInterceptor(auditDataInterceptor);
+            }
+        };
+    }
+}

+ 24 - 3
src/main/java/com/punchsettle/server/core/config/WebMvcConfig.java

@@ -1,13 +1,15 @@
 package com.punchsettle.server.core.config;
 package com.punchsettle.server.core.config;
 
 
-import com.punchsettle.server.common.converter.enums.IntegerToEnumConverterFactory;
-import com.punchsettle.server.core.interceptor.AuthInterceptor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.format.FormatterRegistry;
 import org.springframework.format.FormatterRegistry;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 
+import com.punchsettle.server.common.converter.enums.IntegerToEnumConverterFactory;
+import com.punchsettle.server.core.interceptor.AuthInterceptor;
+
 @Configuration
 @Configuration
 public class WebMvcConfig implements WebMvcConfigurer {
 public class WebMvcConfig implements WebMvcConfigurer {
 
 
@@ -19,8 +21,27 @@ public class WebMvcConfig implements WebMvcConfigurer {
         registry.addConverterFactory(new IntegerToEnumConverterFactory());
         registry.addConverterFactory(new IntegerToEnumConverterFactory());
     }
     }
 
 
+    /**
+     * 登录校验拦截
+     * @param registry
+     */
     @Override
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
     public void addInterceptors(InterceptorRegistry registry) {
-        registry.addInterceptor(authInterceptor).addPathPatterns("/watermark/**", "/oss/**");
+        registry.addInterceptor(authInterceptor)
+                .excludePathPatterns("/health/**", "/login/**");
+    }
+
+    /**
+     * 跨域配置
+     * @param registry
+     */
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**") // 对所有路径生效
+                .allowedOriginPatterns("*") // 允许所有来源
+                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的HTTP方法
+                .allowedHeaders("*") // 允许的头部
+                .allowCredentials(true) // 是否允许发送Cookie
+                .maxAge(3600); // 预检请求的有效期,单位为秒
     }
     }
 }
 }

+ 43 - 27
src/main/java/com/punchsettle/server/core/interceptor/AuthInterceptor.java

@@ -1,48 +1,64 @@
 package com.punchsettle.server.core.interceptor;
 package com.punchsettle.server.core.interceptor;
 
 
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.extern.slf4j.Slf4j;
+import java.util.Map;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
 import org.springframework.web.servlet.HandlerInterceptor;
 import org.springframework.web.servlet.HandlerInterceptor;
 
 
+import com.auth0.jwt.interfaces.Claim;
+import com.punchsettle.server.atomic.entity.User;
+import com.punchsettle.server.atomic.service.IUserService;
+import com.punchsettle.server.common.exception.LoginException;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.utiis.TokenUtils;
+import com.punchsettle.server.utiis.UserUtils;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+
 /**
 /**
+ * @author ChenYL
+ * @version V1.0
  * @className AuthInterceptor
  * @className AuthInterceptor
  * @description 登录权限拦截
  * @description 登录权限拦截
- * @author ChenYL
  * @date 2023/07/29 16:22
  * @date 2023/07/29 16:22
- * @version V1.0
  **/
  **/
 @Slf4j
 @Slf4j
 @Component
 @Component
 public class AuthInterceptor implements HandlerInterceptor {
 public class AuthInterceptor implements HandlerInterceptor {
 
 
-//    @Autowired
-//    private IWechatUserService wechatUserService;
+    @Autowired
+    private IUserService userService;
 
 
     @Override
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
-        throws Exception {
-
-        // String token = request.getHeader("Authorization");
-        // if (!StringUtils.hasText(token)) {
-        // throw LoginException.fail("登录校验异常,原因:没有token凭据");
-        // }
-        //
-        // Long userId = null;
-        // try {
-        // Map<String, Claim> verify = TokenUtils.verify(token);
-        // userId = verify.get("userId").asLong();
-        // } catch (Exception e) {
-        // log.error("登录校验异常,token:{}", token, e);
-        // throw LoginException.fail("登录校验异常");
-        // }
-        //
-        // WechatUserDto wechatUserDto = wechatUserService.getById(userId);
-        // if (wechatUserDto == null) {
-        // throw BusinessException.fail("不存在的用户");
-        // }
+            throws Exception {
+
+        // 判断请求头中是否有token
+        String token = request.getHeader("Authorization");
+        if (!StringUtils.hasText(token)) {
+            throw LoginException.fail("登录校验异常,原因:没有token凭据");
+        }
+
+        // token解析获取用户ID
+        Long currentUserId = null;
+        try {
+            Map<String, Claim> verify = TokenUtils.verify(token);
+            currentUserId = verify.get("userId").asLong();
+        } catch (Exception e) {
+            log.error("登录校验异常,token:{}", token, e);
+            throw LoginException.fail("登录校验异常");
+        }
+
+        // 校验系统中是否存在该用户
+        User currentUser = userService.getById(currentUserId);
+        Assert.isNullInBusiness(currentUser, "不存在的用户");
+
+        // 把用户信息设置如入上下文
+        UserUtils.setCurrentId(currentUser.getId());
 
 
         return true;
         return true;
     }
     }

+ 118 - 0
src/main/java/com/punchsettle/server/core/interceptor/MybatisAuditDataInterceptor.java

@@ -0,0 +1,118 @@
+package com.punchsettle.server.core.interceptor;
+
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.plugin.Intercepts;
+import org.apache.ibatis.plugin.Invocation;
+import org.apache.ibatis.plugin.Signature;
+
+import com.punchsettle.server.common.entity.BaseEntity;
+import com.punchsettle.server.utiis.UserUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2024/11/25 9:56
+ * @description 审计数据拦截器 Mybatis插入/更新时自动填充创建人、创建时间、最后修改人、最后修改时间
+ */
+@Intercepts({
+        @Signature(
+                type = Executor.class,
+                method = "update",
+                args = {MappedStatement.class, Object.class}),
+})
+@Slf4j
+public class MybatisAuditDataInterceptor implements Interceptor {
+
+    @Override
+    public Object intercept(Invocation invocation) throws Throwable {
+        // 对应上面类注解的args,获取需要的MappedStatement对象
+        final Object[] args = invocation.getArgs();
+        MappedStatement statement = (MappedStatement) args[0];
+
+        // 插入对象,即实体类如:SysUser
+        Object obj = args[1];
+
+        /**
+         * 插入或更新的时候,赋予createBy、updateBy、creationTime、lastUpdateTime值
+         */
+        Long currentUserId = Optional.ofNullable(UserUtils.getCurrentUserId()).orElse(1L);
+        Timestamp currentTime = new Timestamp(System.currentTimeMillis());
+
+        // 识别SQL类型,看是INSERT还是UPDATE
+        if (SqlCommandType.INSERT.equals(statement.getSqlCommandType())) {
+            // 单个插入,BaseEntity是我的实体类的父类,该类有id、createBy、updateBy等通用属性
+            if (obj instanceof BaseEntity) {
+                BaseEntity entity = ((BaseEntity) obj);
+                assignInsertDefaultValue(entity, currentUserId, currentTime);
+            }
+            // 批量插入
+            if (obj instanceof Map) {
+                Map<?, ?> map = (Map<?, ?>) obj;
+                List<?> list = (List<?>) map.get("list");
+                if (list != null) {
+                    for (Object entity : list) {
+                        assignInsertDefaultValue((BaseEntity) entity, currentUserId, currentTime);
+                    }
+                }
+            }
+        }
+
+        if (SqlCommandType.UPDATE.equals(statement.getSqlCommandType())) {
+            // 单个更新
+            if (obj instanceof BaseEntity) {
+                BaseEntity entity = ((BaseEntity) obj);
+                assignUpdateDefaultValue(entity, currentUserId, currentTime);
+            }
+            // 批量更新
+            if (obj instanceof Map) {
+                Map<?, ?> map = (Map<?, ?>) obj;
+                List<?> list = (List<?>) map.get("list");
+                if (list != null) {
+                    for (Object item : list) {
+                        BaseEntity entity = ((BaseEntity) item);
+                        assignUpdateDefaultValue(entity, currentUserId, currentTime);
+                    }
+                }
+            }
+        }
+
+        return invocation.proceed();
+    }
+
+    /**
+     * 插入时 赋予createdBy、creationTime、lastUpdatedBy、lastUpdateTime值
+     * @param entity 实体对象
+     * @param currentUserId 当前用户ID
+     * @param currentTime 当前时间时间
+     */
+    private void assignInsertDefaultValue(BaseEntity entity, Long currentUserId, Timestamp currentTime) {
+        entity.setCreatedBy(currentUserId);
+        entity.setCreationTime(currentTime);
+        entity.setLastUpdatedBy(currentUserId);
+        entity.setLastUpdateTime(currentTime);
+        entity.setVersion(1);
+        entity.setDeleteFlag(false);
+    }
+
+    /**
+     * 更新时 赋予lastUpdatedBy、lastUpdateTime值
+     * @param entity 实体对象
+     * @param currentUserId 当前用户ID
+     * @param currentTime 当前时间时间
+     */
+    private void assignUpdateDefaultValue(BaseEntity entity, Long currentUserId, Timestamp currentTime) {
+        entity.setLastUpdatedBy(currentUserId);
+        entity.setLastUpdateTime(currentTime);
+    }
+
+}

+ 20 - 0
src/main/java/com/punchsettle/server/dto/ClaimRewardDto.java

@@ -0,0 +1,20 @@
+package com.punchsettle.server.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 领取结算奖励 dto
+ * @date 2024/11/25 19:42
+ */
+@Data
+@EqualsAndHashCode
+public class ClaimRewardDto {
+
+    /**
+     * 领取奖励数
+     */
+    private Integer claimRewardNum;
+}

+ 65 - 0
src/main/java/com/punchsettle/server/dto/PunchInDto.java

@@ -0,0 +1,65 @@
+package com.punchsettle.server.dto;
+
+import com.punchsettle.server.common.valid.Query;
+import org.hibernate.validator.constraints.Length;
+
+import com.punchsettle.server.common.valid.Delete;
+import com.punchsettle.server.common.valid.DoSomething;
+import com.punchsettle.server.common.valid.Save;
+import com.punchsettle.server.common.valid.Update;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡结算任务信息 dto
+ * @date 2024/11/25 15:01
+ */
+@Data
+@EqualsAndHashCode
+public class PunchInDto {
+
+    /**
+     * 打卡结算主键
+     */
+    @NotNull(message = "打卡结算主键不能为空", groups = {Query.class, Update.class, Delete.class, DoSomething.class})
+    private Long id;
+
+    /**
+     * 版本号
+     */
+    @NotNull(message = "版本号不能为空", groups = {Update.class})
+    @Positive(message = "版本号必须大于0", groups = {Update.class})
+    private Integer version;
+
+    /**
+     * 任务名称
+     */
+    @NotBlank(message = "任务名称不能为空", groups = {Save.class, Update.class})
+    @Length(max = 30, message = "任务名称不能超过30个字符", groups = {Save.class, Update.class})
+    private String taskName;
+
+    /**
+     * 奖励倍数
+     */
+    @NotNull(message = "奖励倍数不能为空", groups = {Save.class, Update.class})
+    @Positive(message = "奖励倍数必须大于0", groups = {Save.class, Update.class})
+    private Integer rewardNum;
+
+    /**
+     * 是否启用周末双倍标志(0-不是,1-是)
+     */
+    @NotNull(message = "是否启用周末双倍标志不能为空", groups = {Save.class, Update.class})
+    private Boolean weekendDoubleFlag;
+
+    /**
+     * 是否启用全勤奖励标志(0-不是,1-是)
+     */
+    @NotNull(message = "是否启用全勤奖励标志不能为空", groups = {Save.class, Update.class})
+    private Boolean fullAttendanceFlag;
+}

+ 27 - 0
src/main/java/com/punchsettle/server/dto/PunchInRecordDto.java

@@ -0,0 +1,27 @@
+package com.punchsettle.server.dto;
+
+import com.punchsettle.server.constant.PunchInStatusEnum;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡记录
+ * @date 2024/11/25 16:24
+ */
+@Data
+@EqualsAndHashCode
+public class PunchInRecordDto {
+
+    /**
+     * 打卡日期
+     */
+    private String punchInDate;
+
+    /**
+     * 打卡状态
+     * @see PunchInStatusEnum
+     */
+    private PunchInStatusEnum punchInStatus;
+}

+ 32 - 0
src/main/java/com/punchsettle/server/dto/PunchInRecordQuery.java

@@ -0,0 +1,32 @@
+package com.punchsettle.server.dto;
+
+import java.util.List;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡记录查询 dto
+ * @date 2024/11/25 16:09
+ */
+@Data
+@EqualsAndHashCode
+public class PunchInRecordQuery {
+
+    /**
+     * 打卡任务主键
+     */
+    private List<Long> punchInIds;
+
+    /**
+     * 打卡日期范围-开始日期
+     */
+    private String startDate;
+
+    /**
+     * 打卡日期范围-结束日期
+     */
+    private String endDate;
+}

+ 50 - 0
src/main/java/com/punchsettle/server/dto/PunchInWithRecordDto.java

@@ -0,0 +1,50 @@
+package com.punchsettle.server.dto;
+
+import java.util.List;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务并带有打卡记录信息 dto
+ * @date 2024/11/25 15:41
+ */
+@Data
+public class PunchInWithRecordDto {
+
+    /**
+     * 打卡任务主键
+     */
+    private Long punchInId;
+
+    /**
+     * 任务名称
+     */
+    private String taskName;
+
+    /**
+     * 奖励倍数
+     */
+    private Integer rewardNum;
+
+    /**
+     * 是否启用周末双倍标志(0-不是,1-是)
+     */
+    private Boolean weekendDoubleFlag;
+
+    /**
+     * 是否启用全勤奖励标志(0-不是,1-是)
+     */
+    private Boolean fullAttendanceFlag;
+
+    /**
+     * 是否归档标志(0-不是,1-是)
+     */
+    private Boolean archiveFlag;
+
+    /**
+     * 打卡记录
+     */
+    private List<PunchInRecordDto> punchInRecords;
+}

+ 18 - 0
src/main/java/com/punchsettle/server/dto/UserRewardDto.java

@@ -0,0 +1,18 @@
+package com.punchsettle.server.dto;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 用户奖励
+ * @date 2024/11/25 20:55
+ */
+@Data
+public class UserRewardDto {
+
+    /**
+     * 未领取奖励数
+     */
+    private Integer unclaimedRewardNum;
+}

+ 1 - 0
src/main/java/com/punchsettle/server/dto/wechat/Code2SessionResponse.java

@@ -1,6 +1,7 @@
 package com.punchsettle.server.dto.wechat;
 package com.punchsettle.server.dto.wechat;
 
 
 import com.fasterxml.jackson.annotation.JsonAlias;
 import com.fasterxml.jackson.annotation.JsonAlias;
+
 import lombok.Data;
 import lombok.Data;
 
 
 /**
 /**

+ 3 - 2
src/main/java/com/punchsettle/server/feign/WechatMiniProgramFeign.java

@@ -1,11 +1,12 @@
 package com.punchsettle.server.feign;
 package com.punchsettle.server.feign;
 
 
-import com.punchsettle.server.dto.wechat.Code2SessionRequest;
-import com.punchsettle.server.dto.wechat.Code2SessionResponse;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.cloud.openfeign.SpringQueryMap;
 import org.springframework.cloud.openfeign.SpringQueryMap;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 
 
+import com.punchsettle.server.dto.wechat.Code2SessionRequest;
+import com.punchsettle.server.dto.wechat.Code2SessionResponse;
+
 /**
 /**
  * @interfaceNName WeChatMiniProgramFeign
  * @interfaceNName WeChatMiniProgramFeign
  * @description 微信小程序服务接口
  * @description 微信小程序服务接口

+ 10 - 10
src/main/java/com/punchsettle/server/service/controller/WechatMiniProgramController.java → src/main/java/com/punchsettle/server/service/controller/LoginController.java

@@ -1,26 +1,26 @@
 package com.punchsettle.server.service.controller;
 package com.punchsettle.server.service.controller;
 
 
-import com.punchsettle.server.dto.wechat.LoginRequest;
-import com.punchsettle.server.service.manager.IWechatMiniProgramManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
+import com.punchsettle.server.dto.wechat.LoginRequest;
+import com.punchsettle.server.service.manager.ILoginManager;
+
 /**
 /**
- * @className WeChatMiniProgramController
- * @description 微信小程序
+ * @className LoginController
+ * @description 登录 controller
  * @author ChenYL
  * @author ChenYL
  * @date 2023/07/23 16:08
  * @date 2023/07/23 16:08
  * @version V1.0
  * @version V1.0
  **/
  **/
 @RestController
 @RestController
-@RequestMapping("/wechat/miniprogram")
-public class WechatMiniProgramController {
+public class LoginController {
 
 
     @Autowired
     @Autowired
-    private IWechatMiniProgramManager weChatMiniProgramManager;
+    private ILoginManager loginManager;
 
 
     /**
     /**
      * 微信小程序登录
      * 微信小程序登录
@@ -28,8 +28,8 @@ public class WechatMiniProgramController {
      * @param request
      * @param request
      * @return 微信登陆后获得的session_key
      * @return 微信登陆后获得的session_key
      */
      */
-    @PostMapping("/login")
-    public String login(@RequestBody LoginRequest request) {
-        return weChatMiniProgramManager.login(request);
+    @PostMapping("/wechat/miniprogram/login")
+    public String wechatMiniProgramLogin(@RequestBody LoginRequest request) {
+        return loginManager.wechatMiniProgramLogin(request);
     }
     }
 }
 }

+ 79 - 0
src/main/java/com/punchsettle/server/service/controller/PunchInController.java

@@ -0,0 +1,79 @@
+package com.punchsettle.server.service.controller;
+
+import java.util.List;
+
+import com.punchsettle.server.common.valid.Query;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.punchsettle.server.common.valid.Delete;
+import com.punchsettle.server.common.valid.DoSomething;
+import com.punchsettle.server.common.valid.Save;
+import com.punchsettle.server.common.valid.Update;
+import com.punchsettle.server.dto.PunchInDto;
+import com.punchsettle.server.dto.PunchInWithRecordDto;
+import com.punchsettle.server.service.manager.IPunchInManager;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡任务 controller
+ * @date 2024/11/25 14:48
+ */
+@RestController
+@RequestMapping("/punchIn")
+public class PunchInController {
+
+    @Autowired
+    private IPunchInManager punchInManager;
+
+    /**
+     * 查询打卡任务
+     */
+    @GetMapping("/queryPunchIn")
+    public List<PunchInWithRecordDto> query() {
+        return punchInManager.queryPunchInAndRecord();
+    }
+
+    @PostMapping("queryPunchInById")
+    public PunchInDto queryPunchInById(@RequestBody @Validated({Query.class}) PunchInDto dto) {
+        return punchInManager.queryPunchInById(dto.getId());
+    }
+
+    /**
+     * 新增打卡任务
+     */
+    @PostMapping("/savePunchIn")
+    public void save(@RequestBody @Validated({Save.class}) PunchInDto dto) {
+        punchInManager.saveOrUpdatePunchIn(dto);
+    }
+
+    /**
+     * 更新打卡任务
+     */
+    @PostMapping("/updatePunchIn")
+    public void update(@RequestBody @Validated({Update.class}) PunchInDto dto) {
+        punchInManager.saveOrUpdatePunchIn(dto);
+    }
+
+    /**
+     * 删除打卡任务
+     */
+    @PostMapping("/deletePunchIn")
+    public void delete(@RequestBody @Validated({Delete.class}) PunchInDto dto) {
+        punchInManager.deletePunchIn(dto.getId());
+    }
+
+    /**
+     * 打卡
+     */
+    @PostMapping("/doPunchIn")
+    public void doPunchIn(@RequestBody @Validated({DoSomething.class}) PunchInDto dto) {
+        punchInManager.doPunchIn(dto.getId());
+    }
+}

+ 44 - 0
src/main/java/com/punchsettle/server/service/controller/RewardController.java

@@ -0,0 +1,44 @@
+package com.punchsettle.server.service.controller;
+
+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.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.punchsettle.server.dto.ClaimRewardDto;
+import com.punchsettle.server.dto.UserRewardDto;
+import com.punchsettle.server.service.manager.IRewardManager;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 奖励 controller
+ * @date 2024/11/26 15:00
+ */
+@RestController
+@RequestMapping("/reward")
+public class RewardController {
+
+    @Autowired
+    private IRewardManager rewardManager;
+
+    /**
+     * 查询奖励
+     * @return
+     */
+    @GetMapping("/queryReward")
+    public UserRewardDto queryReward() {
+        return rewardManager.queryReward();
+    }
+
+    /**
+     * 领取奖励
+     * @param dto
+     */
+    @PostMapping("/claimReward")
+    public void claimReward(@RequestBody ClaimRewardDto dto) {
+        rewardManager.claimReward(dto);
+    }
+}

+ 30 - 0
src/main/java/com/punchsettle/server/service/controller/TaskController.java

@@ -0,0 +1,30 @@
+package com.punchsettle.server.service.controller;
+
+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 com.punchsettle.server.service.manager.ITaskManager;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 结算定时任务 controller
+ * @date 2024/11/26 15:04
+ */
+@RestController
+@RequestMapping("/task")
+public class TaskController {
+
+    @Autowired
+    private ITaskManager taskManager;
+
+    /**
+     * 手动调起结算定时任务
+     */
+    @GetMapping("/manualSettle")
+    public void manualSettle() {
+        taskManager.autoSettle();
+    }
+}

+ 3 - 3
src/main/java/com/punchsettle/server/service/manager/IWechatMiniProgramManager.java → src/main/java/com/punchsettle/server/service/manager/ILoginManager.java

@@ -3,9 +3,9 @@ package com.punchsettle.server.service.manager;
 import com.punchsettle.server.dto.wechat.LoginRequest;
 import com.punchsettle.server.dto.wechat.LoginRequest;
 
 
 /**
 /**
- * 微信小程序 服务类
+ * 登录 服务类
  */
  */
-public interface IWechatMiniProgramManager {
+public interface ILoginManager {
 
 
     /**
     /**
      * 微信小程序登录
      * 微信小程序登录
@@ -13,5 +13,5 @@ public interface IWechatMiniProgramManager {
      * @param request
      * @param request
      * @return 微信登陆后获得的session_key
      * @return 微信登陆后获得的session_key
      */
      */
-    String login(LoginRequest request);
+    String wechatMiniProgramLogin(LoginRequest request);
 }
 }

+ 44 - 0
src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java

@@ -0,0 +1,44 @@
+package com.punchsettle.server.service.manager;
+
+import java.util.List;
+
+import com.punchsettle.server.dto.PunchInDto;
+import com.punchsettle.server.dto.PunchInWithRecordDto;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡结算任务 服务类
+ * @date 2024/11/25 15:00
+ */
+public interface IPunchInManager {
+
+    /**
+     * 查询打卡任务及其打卡记录
+     * @return
+     */
+    List<PunchInWithRecordDto> queryPunchInAndRecord();
+
+    /**
+     * 根据ID获取打卡任务
+     */
+    PunchInDto queryPunchInById(Long punchInId);
+
+    /**
+     * 新增或更新打卡结算任务
+     * @param dto 打卡结算
+     */
+    void saveOrUpdatePunchIn(PunchInDto dto);
+
+    /**
+     * 根据主键删除打卡结算任务
+     * @param punchInId 主键
+     */
+    void deletePunchIn(Long punchInId);
+
+    /**
+     * 完成打卡结算任务插入打卡记录
+     * @param punchInId 主键
+     */
+    void doPunchIn(Long punchInId);
+}

+ 25 - 0
src/main/java/com/punchsettle/server/service/manager/IRewardManager.java

@@ -0,0 +1,25 @@
+package com.punchsettle.server.service.manager;
+
+import com.punchsettle.server.dto.ClaimRewardDto;
+import com.punchsettle.server.dto.UserRewardDto;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 奖励服务类
+ * @date 2024/11/25 20:52
+ */
+public interface IRewardManager {
+
+    /**
+     * 领取奖励
+     * @param dto
+     */
+    void claimReward(ClaimRewardDto dto);
+
+    /**
+     * 查询当前用户拥有的奖励数
+     * @return
+     */
+    UserRewardDto queryReward();
+}

+ 15 - 0
src/main/java/com/punchsettle/server/service/manager/ITaskManager.java

@@ -0,0 +1,15 @@
+package com.punchsettle.server.service.manager;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 定时任务服务类
+ * @date 2024/11/26 9:19
+ */
+public interface ITaskManager {
+
+    /**
+     * 结算定时任务
+     */
+    void autoSettle();
+}

+ 22 - 24
src/main/java/com/punchsettle/server/service/manager/impl/WechatMiniProgramManagerImpl.java → src/main/java/com/punchsettle/server/service/manager/impl/LoginManagerImpl.java

@@ -1,44 +1,46 @@
 package com.punchsettle.server.service.manager.impl;
 package com.punchsettle.server.service.manager.impl;
 
 
 
 
+import java.util.Calendar;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.punchsettle.server.atomic.entity.User;
+import com.punchsettle.server.atomic.service.IUserService;
 import com.punchsettle.server.common.exception.BusinessException;
 import com.punchsettle.server.common.exception.BusinessException;
-import com.punchsettle.server.core.config.BizConfig;
+import com.punchsettle.server.common.utils.Assert;
 import com.punchsettle.server.constant.CacheConstant;
 import com.punchsettle.server.constant.CacheConstant;
+import com.punchsettle.server.core.config.BizConfig;
 import com.punchsettle.server.dto.wechat.Code2SessionRequest;
 import com.punchsettle.server.dto.wechat.Code2SessionRequest;
 import com.punchsettle.server.dto.wechat.Code2SessionResponse;
 import com.punchsettle.server.dto.wechat.Code2SessionResponse;
 import com.punchsettle.server.dto.wechat.LoginRequest;
 import com.punchsettle.server.dto.wechat.LoginRequest;
 import com.punchsettle.server.feign.WechatMiniProgramFeign;
 import com.punchsettle.server.feign.WechatMiniProgramFeign;
-import com.punchsettle.server.service.manager.IWechatMiniProgramManager;
+import com.punchsettle.server.service.manager.ILoginManager;
 import com.punchsettle.server.utiis.CacheUtils;
 import com.punchsettle.server.utiis.CacheUtils;
 import com.punchsettle.server.utiis.TokenUtils;
 import com.punchsettle.server.utiis.TokenUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.CacheManager;
-import org.springframework.stereotype.Service;
 
 
-import java.util.Calendar;
+import lombok.extern.slf4j.Slf4j;
 
 
 /**
 /**
- * 微信小程序服务类
+ * 登录服务类
  */
  */
 @Slf4j
 @Slf4j
 @Service
 @Service
-public class WechatMiniProgramManagerImpl implements IWechatMiniProgramManager {
+public class LoginManagerImpl implements ILoginManager {
 
 
     @Autowired
     @Autowired
     private WechatMiniProgramFeign wechatMiniProgramFeign;
     private WechatMiniProgramFeign wechatMiniProgramFeign;
 
 
-//    @Autowired
-//    private IWechatUserService wechatUserService;
-
     @Autowired
     @Autowired
-    private CacheManager cacheManager;
+    private IUserService userService;
 
 
     @Autowired
     @Autowired
     private BizConfig bizConfig;
     private BizConfig bizConfig;
 
 
     @Override
     @Override
-    public String login(LoginRequest request) {
+    public String wechatMiniProgramLogin(LoginRequest request) {
+        // 从微信获取session_key
         Code2SessionRequest code2SessionRequest = new Code2SessionRequest();
         Code2SessionRequest code2SessionRequest = new Code2SessionRequest();
         code2SessionRequest.setGrantType("authorization_code");
         code2SessionRequest.setGrantType("authorization_code");
         code2SessionRequest.setJsCode(request.getCode());
         code2SessionRequest.setJsCode(request.getCode());
@@ -48,22 +50,18 @@ public class WechatMiniProgramManagerImpl implements IWechatMiniProgramManager {
         }
         }
 
 
         // 获取用户记录
         // 获取用户记录
-//        WechatUser wechatUser = wechatUserService.getAndAdd(loginResponse.getOpenId());
-//        if (wechatUser == null) {
-//            throw BusinessException.fail(String.format("不存在的用户,且无法新增,openid: %s", loginResponse.getOpenId()));
-//        }
+        User user = userService.getAndAdd(loginResponse.getOpenId());
+        Assert.isNullInBusiness(user, String.format("不存在的用户,且无法新增,openid: %s", loginResponse.getOpenId()));
 
 
         // 缓存微信用户对应的session_key
         // 缓存微信用户对应的session_key
-        CacheUtils.put(CacheConstant.WECHAT_MINI_PROGRAM_SESSION_KEY, loginResponse.getOpenId(),
+        CacheUtils.put(CacheConstant.WECHAT_MINI_PROGRAM_SESSION_KEY, user.getId().toString(),
             loginResponse.getSessionKey());
             loginResponse.getSessionKey());
 
 
-        // 创建token并缓存
+        // 创建token
         Calendar instance = Calendar.getInstance();
         Calendar instance = Calendar.getInstance();
         instance.add(Calendar.DATE, bizConfig.getTokenExpire());
         instance.add(Calendar.DATE, bizConfig.getTokenExpire());
-//        String token = TokenUtils.createToken(wechatUser.getId(), instance.getTime());
-//        CacheUtils.put(CacheConstant.SYSTEM_USER_TOKEN, loginResponse.getOpenId(), token);
+        String token = TokenUtils.createToken(user.getId(), instance.getTime());
 
 
-//        return token;
-        return null;
+        return token;
     }
     }
 }
 }

+ 173 - 0
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -0,0 +1,173 @@
+package com.punchsettle.server.service.manager.impl;
+
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.entity.PunchIn;
+import com.punchsettle.server.atomic.entity.PunchInRecord;
+import com.punchsettle.server.atomic.service.IPunchInRecordService;
+import com.punchsettle.server.atomic.service.IPunchInService;
+import com.punchsettle.server.common.exception.BusinessException;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.constant.PunchInStatusEnum;
+import com.punchsettle.server.dto.PunchInDto;
+import com.punchsettle.server.dto.PunchInRecordDto;
+import com.punchsettle.server.dto.PunchInRecordQuery;
+import com.punchsettle.server.dto.PunchInWithRecordDto;
+import com.punchsettle.server.service.manager.IPunchInManager;
+import com.punchsettle.server.utiis.DateUtils;
+import com.punchsettle.server.utiis.UserUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡结算任务 服务类
+ * @date 2024/11/25 15:12
+ */
+@Slf4j
+@Service
+public class PunchInManagerImpl implements IPunchInManager {
+
+    @Autowired
+    private IPunchInService punchInService;
+
+    @Autowired
+    private IPunchInRecordService punchInRecordService;
+
+    @Override
+    public List<PunchInWithRecordDto> queryPunchInAndRecord() {
+        // 获取当前用户ID
+        Long currentUserId = Optional.ofNullable(UserUtils.getCurrentUserId())
+            .orElseThrow(() -> BusinessException.fail("无法获取当前用户信息,无法查询打卡任务"));
+
+        // 查询打卡任务
+        List<PunchIn> punchIns = punchInService.listByCreatedBy(currentUserId);
+        if (CollectionUtils.isEmpty(punchIns)) {
+            log.info("用户:{} 没有查询到生效的打卡任务");
+            return List.of();
+        }
+
+        // 获取一周的起始日期范围,
+        List<LocalDate> weeklyDateRange = DateUtils.getWeeklyDateRange();
+        // 获取打卡任务ID
+        List<Long> punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList());
+        // 找出范围内的打卡记录
+        PunchInRecordQuery query = new PunchInRecordQuery();
+        query.setPunchInIds(punchInIds);
+        query.setStartDate(weeklyDateRange.getFirst().toString());
+        query.setEndDate(weeklyDateRange.getLast().toString());
+        List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(query);
+
+        // 按打卡任务任务分组
+        Map<Long, List<PunchInRecord>> recordMap =
+            punchInRecords.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
+
+        // 日期格式化
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+
+        // 当前日期
+        LocalDate today = LocalDate.now();
+
+        // 构建打卡记录
+        List<PunchInWithRecordDto> punchInWithRecordDtos = new ArrayList<>();
+        for (PunchIn punchIn : punchIns) {
+            PunchInWithRecordDto punchInWithRecordDto = new PunchInWithRecordDto();
+            BeanUtils.copyProperties(punchIn, punchInWithRecordDto);
+            punchInWithRecordDto.setPunchInId(punchIn.getId());
+
+            // 打卡任务创建日期
+            LocalDate punchInCreationDate = LocalDate.parse(sdf.format(punchIn.getCreationTime()));
+
+            // 获取打卡任务对应的打卡记录,并按打卡日期转为map
+            List<PunchInRecord> records =
+                Optional.ofNullable(recordMap.get(punchInWithRecordDto.getPunchInId())).orElse(List.of());
+            Map<String, PunchInRecord> recordWeekMap = records.stream()
+                .collect(Collectors.toMap(PunchInRecord::getPunchInDate, Function.identity(), (key1, key2) -> key1));
+
+            // 设置打卡记录
+            List<PunchInRecordDto> recordDtos = new ArrayList<>();
+            punchInWithRecordDto.setPunchInRecords(recordDtos);
+
+            // 知道任务什么时候创建
+            // 在这之前(不包含)的记录的状态值都为0-任务未创建
+            // 在这之后如果打卡则状态为1-任务已创建已打卡
+            // 在这之后如果没打卡则状态为2-任务已创建但未打卡
+            // 如果当前日期超过一周中的某天则跳过
+            for (LocalDate currentDate : weeklyDateRange) {
+                String currentDateStr = currentDate.toString();
+                // 设置打卡记录
+                PunchInRecordDto punchInRecordDto = new PunchInRecordDto();
+                punchInRecordDto.setPunchInDate(currentDateStr);
+                recordDtos.add(punchInRecordDto);
+
+                // 还没到当前日期则跳过,根据过往打卡记录设置打卡状态
+                if (currentDate.isAfter(today)) {
+                    punchInRecordDto.setPunchInStatus(PunchInStatusEnum.FUTURE_TIME);
+                } else if (currentDate.isBefore(punchInCreationDate)) {
+                    punchInRecordDto.setPunchInStatus(PunchInStatusEnum.UNCREATED);
+                } else if (recordWeekMap.containsKey(currentDateStr)) {
+                    punchInRecordDto.setPunchInStatus(PunchInStatusEnum.PUNCH_IN);
+                } else if (currentDate.isEqual(today) && !recordWeekMap.containsKey(currentDateStr)) {
+                    punchInRecordDto.setPunchInStatus(PunchInStatusEnum.TODAY_UNKNOWN);
+                } else {
+                    punchInRecordDto.setPunchInStatus(PunchInStatusEnum.UN_PUNCH_IN);
+                }
+
+            }
+            punchInWithRecordDtos.add(punchInWithRecordDto);
+        }
+
+        return punchInWithRecordDtos;
+    }
+
+    @Override
+    public PunchInDto queryPunchInById(Long punchInId) {
+        Assert.isNullInBusiness(punchInId, "请传入待查询的任务ID");
+        return Optional.ofNullable(punchInService.getById(punchInId)).map(punchIn -> {
+            PunchInDto dto = new PunchInDto();
+            BeanUtils.copyProperties(punchIn, dto);
+            return dto;
+        }).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
+    }
+
+    @Override
+    public void saveOrUpdatePunchIn(PunchInDto dto) {
+        Assert.isNullInBusiness(dto, "请传入任务信息");
+
+        PunchIn punchIn = new PunchIn();
+        BeanUtils.copyProperties(dto, punchIn);
+        punchIn.setArchiveFlag(false);
+        punchInService.insertOrUpdate(punchIn);
+    }
+
+    @Override
+    public void deletePunchIn(Long punchInId) {
+        Assert.isNullInBusiness(punchInId, "请传入待删除的任务");
+        punchInService.delete(punchInId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void doPunchIn(Long punchInId) {
+        Assert.isNullInBusiness(punchInId, "请传入待打卡的任务");
+        // 创建打卡记录
+        PunchInRecord punchInRecord = new PunchInRecord();
+        punchInRecord.setPunchInId(punchInId);
+        punchInRecord.setPunchInDate(LocalDate.now().toString());
+        punchInRecordService.insert(punchInRecord);
+    }
+}

+ 81 - 0
src/main/java/com/punchsettle/server/service/manager/impl/RewardManagerImpl.java

@@ -0,0 +1,81 @@
+package com.punchsettle.server.service.manager.impl;
+
+import java.sql.Timestamp;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.punchsettle.server.atomic.entity.UserClaimRewardRecord;
+import com.punchsettle.server.atomic.entity.UserReward;
+import com.punchsettle.server.atomic.service.IUserClaimRewardRecordService;
+import com.punchsettle.server.atomic.service.IUserRewardService;
+import com.punchsettle.server.common.exception.BusinessException;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.dto.ClaimRewardDto;
+import com.punchsettle.server.dto.UserRewardDto;
+import com.punchsettle.server.service.manager.IRewardManager;
+import com.punchsettle.server.utiis.UserUtils;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 奖励 服务类
+ * @date 2024/11/25 20:59
+ */
+@Service
+public class RewardManagerImpl implements IRewardManager {
+
+    @Autowired
+    private IUserClaimRewardRecordService userClaimRewardRecordService;
+
+    @Autowired
+    private IUserRewardService userRewardService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void claimReward(ClaimRewardDto dto) {
+        if (Objects.isNull(dto) || Objects.isNull(dto.getClaimRewardNum())) {
+            throw BusinessException.fail("待领取的奖励数不能为空");
+        }
+
+        // 获取用户信息
+        Long currentUserId =
+            Optional.ofNullable(UserUtils.getCurrentUserId()).orElseThrow(() -> BusinessException.fail("无法获取当前用户ID"));
+        UserReward userReward = Optional.ofNullable(userRewardService.getByUserId(currentUserId)).orElseThrow(() -> BusinessException.fail("无法获取当前用户的奖励信息"));
+
+        // 计算未领取奖励数、已领取奖励数
+        if (userReward.getUnclaimedRewardNum() < dto.getClaimRewardNum()) {
+            throw BusinessException.fail("当前用户奖励不足,无法领取");
+        }
+        int unclaimedRewardNum = userReward.getUnclaimedRewardNum() - dto.getClaimRewardNum();
+        int claimedRewardNum = userReward.getClaimedRewardNum() + dto.getClaimRewardNum();
+
+        // 构建打卡记录
+        UserClaimRewardRecord userClaimRewardRecord = new UserClaimRewardRecord();
+        userClaimRewardRecord.setUserId(currentUserId);
+        userClaimRewardRecord.setClaimRewardNum(dto.getClaimRewardNum());
+        userClaimRewardRecord.setClaimRewardTime(new Timestamp(System.currentTimeMillis()));
+        userClaimRewardRecord.setBeforeClaimRewardNum(userReward.getUnclaimedRewardNum());
+        userClaimRewardRecord.setAfterClaimRewardNum(unclaimedRewardNum);
+        userClaimRewardRecordService.insert(userClaimRewardRecord);
+
+        // 更新用户奖励信息
+        userReward.setUnclaimedRewardNum(unclaimedRewardNum);
+        userReward.setClaimedRewardNum(claimedRewardNum);
+        userRewardService.updateReward(userReward);
+    }
+
+    @Override
+    public UserRewardDto queryReward() {
+        Long currentUserId = UserUtils.getCurrentUserId();
+        UserReward userReward = userRewardService.getByUserId(currentUserId);
+        Assert.isNullInBusiness(userReward, "用户没有奖励信息");
+
+        UserRewardDto userRewardDto = new UserRewardDto();
+        userRewardDto.setUnclaimedRewardNum(userReward.getUnclaimedRewardNum());
+        return userRewardDto;
+    }
+}

+ 224 - 0
src/main/java/com/punchsettle/server/service/manager/impl/TaskManagerImpl.java

@@ -0,0 +1,224 @@
+package com.punchsettle.server.service.manager.impl;
+
+import java.sql.Timestamp;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.entity.PunchIn;
+import com.punchsettle.server.atomic.entity.PunchInRecord;
+import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela;
+import com.punchsettle.server.atomic.entity.PunchInSettlement;
+import com.punchsettle.server.atomic.entity.SettlementTask;
+import com.punchsettle.server.atomic.entity.UserReward;
+import com.punchsettle.server.atomic.service.IPunchInRecordService;
+import com.punchsettle.server.atomic.service.IPunchInRecordSettlementRelaService;
+import com.punchsettle.server.atomic.service.IPunchInService;
+import com.punchsettle.server.atomic.service.IPunchInSettlementService;
+import com.punchsettle.server.atomic.service.ISettlementTaskService;
+import com.punchsettle.server.atomic.service.IUserRewardService;
+import com.punchsettle.server.dto.PunchInRecordQuery;
+import com.punchsettle.server.service.manager.ITaskManager;
+import com.punchsettle.server.utiis.DateUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 打卡结算服务
+ * @date 2024/11/26 9:20
+ */
+@Service
+@Slf4j
+public class TaskManagerImpl implements ITaskManager {
+
+    @Autowired
+    private IPunchInService punchInService;
+
+    @Autowired
+    private IPunchInRecordService punchInRecordService;
+
+    @Autowired
+    private IUserRewardService userRewardService;
+
+    @Autowired
+    private IPunchInSettlementService punchInSettlementService;
+
+    @Autowired
+    private ISettlementTaskService settlementTaskService;
+
+    @Autowired
+    private IPunchInRecordSettlementRelaService punchInRecordSettlementRelaService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void autoSettle() {
+        log.info("结算任务开始");
+        Timestamp settleStartTime = new Timestamp(System.currentTimeMillis());
+
+        // 获取昨天的日期,
+        LocalDate yesterday = DateUtils.getYesterdayDate();
+        String yesterdayStr = DateUtils.getYesterdayDateStr();
+        // 判断是否是周末
+        boolean weekendFlag =
+            DayOfWeek.SATURDAY.equals(yesterday.getDayOfWeek()) || DayOfWeek.SUNDAY.equals(yesterday.getDayOfWeek());
+        boolean sundayFlag = DayOfWeek.SUNDAY.equals(yesterday.getDayOfWeek());
+
+        PunchInRecordQuery recordQuery = new PunchInRecordQuery();
+        recordQuery.setStartDate(yesterdayStr);
+        recordQuery.setEndDate(yesterdayStr);
+        List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
+        if (CollectionUtils.isEmpty(punchInRecords)) {
+            log.info("结算任务结束,原因:没有打卡记录");
+            return;
+        }
+
+        List<Long> userIds = punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList());
+
+        // 读取用户的打卡任务
+        List<PunchIn> punchIns = punchInService.listByCreatedBy(userIds);
+        if (CollectionUtils.isEmpty(punchIns)) {
+            log.info("结算任务结束,原因:根据打卡记录没有找到打卡任务");
+            return;
+        }
+
+        // 读取用户奖励数据
+        List<UserReward> userRewards = userRewardService.listByUserIds(userIds);
+        if (CollectionUtils.isEmpty(userRewards)) {
+            log.info("结算任务结束,原因:没有找到用户奖励信息");
+            return;
+        }
+
+        // 获取一周的打卡记录
+        Map<Long, List<PunchInRecord>> punchInRecordForWeek = Map.of();
+        if (sundayFlag) {
+            List<Long> punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList());
+            PunchInRecordQuery recordForWeekQuery = new PunchInRecordQuery();
+            recordForWeekQuery.setPunchInIds(punchInIds);
+            recordForWeekQuery.setStartDate(DateUtils.getLastWeekMondayStr());
+            recordForWeekQuery.setEndDate(DateUtils.getLastWeekSundayStr());
+            List<PunchInRecord> punchInRecordForWeeks = punchInRecordService.listByCondition(recordForWeekQuery);
+            if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) {
+                punchInRecordForWeek =
+                    punchInRecordForWeeks.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
+            }
+        }
+
+        // 打卡任务容器
+        Map<Long, PunchIn> punchInMap =
+            punchIns.stream().collect(Collectors.toMap(PunchIn::getId, Function.identity(), (key1, key2) -> key1));
+
+        // 用户-打卡记录分组
+        Map<Long, List<PunchInRecord>> userPunchInRecordMap =
+            punchInRecords.stream().collect(Collectors.groupingBy(PunchInRecord::getCreatedBy));
+
+        // 用户-奖励分组
+        Map<Long, UserReward> userRewardMap = userRewards.stream()
+            .collect(Collectors.toMap(UserReward::getUserId, Function.identity(), (key1, key2) -> key1));
+
+        // 先创建结算任务执行记录
+        SettlementTask settlementTask = new SettlementTask();
+        settlementTask.setSettleDate(yesterdayStr);
+        settlementTask.setStartTime(settleStartTime);
+        settlementTask.setProcessedNum(userPunchInRecordMap.size());
+        settlementTaskService.insert(settlementTask);
+
+        // 结算时间
+        Timestamp settlementTime = new Timestamp(System.currentTimeMillis());
+        List<PunchInSettlement> addPunchInSettlements = new ArrayList<>();
+        List<UserReward> updateUserRewards = new ArrayList<>();
+        List<PunchInRecordSettlementRela> punchInRecordSettlementRelas = new ArrayList<>();
+
+        // 有打卡记录的打卡任务则进行结算
+        for (Long userId : userPunchInRecordMap.keySet()) {
+            // 获取用户打卡记录
+            List<PunchInRecord> punchInRecordList = userPunchInRecordMap.get(userId);
+            if (CollectionUtils.isEmpty(punchInRecordList)) {
+                log.info("用户{}没有打卡记录,无须结算", userId);
+                continue;
+            }
+            // 获取用户打卡奖励
+            UserReward userReward = userRewardMap.get(userId);
+            if (Objects.isNull(userReward)) {
+                log.info("用户{}没有奖励信息,无法结算", userId);
+                continue;
+            }
+
+            // 根据打卡记录上的打卡任务ID获取具体的打卡任务信息进行结算
+            int settleRewardNum = 0;
+            for (PunchInRecord punchInRecord : punchInRecordList) {
+                PunchIn punchIn = punchInMap.get(punchInRecord.getPunchInId());
+                if (Objects.isNull(punchIn)) {
+                    continue;
+                }
+                // 周末双倍奖励,否则计算普通奖励
+                settleRewardNum += weekendFlag ? punchIn.getRewardNum() * 2 : punchIn.getRewardNum();
+                // 周日计算一次全勤双倍奖励
+                if (sundayFlag && punchIn.getFullAttendanceFlag()) {
+                    List<PunchInRecord> tempRecordList = punchInRecordForWeek.get(punchInRecord.getPunchInId());
+                    if (!CollectionUtils.isEmpty(tempRecordList) && tempRecordList.size() >= 6) {
+                        settleRewardNum += punchIn.getRewardNum() * 2;
+                    }
+                }
+
+                // 构建结算任务与记录关联信息
+                PunchInRecordSettlementRela rela = new PunchInRecordSettlementRela();
+                rela.setRecordId(punchInRecord.getId());
+                rela.setSettlementId(settlementTask.getId());
+                punchInRecordSettlementRelas.add(rela);
+            }
+
+            // 计算结算前后,用户奖励数的变化
+            int beforeSettleRewardNum = userReward.getUnclaimedRewardNum();
+            int afterSettleRewardNum = beforeSettleRewardNum + settleRewardNum;
+            int totalRewardNum = userReward.getTotalRewardNum() + settleRewardNum;
+
+            // 构造结算信息
+            PunchInSettlement addPunchInSettlement = new PunchInSettlement();
+            addPunchInSettlement.setSettlementTaskId(settlementTask.getId());
+            addPunchInSettlement.setUserId(userId);
+            addPunchInSettlement.setSettleRewardNum(settleRewardNum);
+            addPunchInSettlement.setSettlementTime(settlementTime);
+            addPunchInSettlement.setBeforeSettleRewardNum(beforeSettleRewardNum);
+            addPunchInSettlement.setAfterSettleRewardNum(afterSettleRewardNum);
+            addPunchInSettlements.add(addPunchInSettlement);
+
+            // 构造用户奖励信息
+            UserReward updateUserReward = new UserReward();
+            updateUserReward.setId(userReward.getId());
+            updateUserReward.setVersion(userReward.getVersion());
+            updateUserReward.setTotalRewardNum(totalRewardNum);
+            updateUserReward.setUnclaimedRewardNum(afterSettleRewardNum);
+            updateUserRewards.add(updateUserReward);
+        }
+
+        // 更新用户奖励信息
+        userRewardService.batchUpdateUserReward(updateUserRewards);
+
+        // 新增结算信息
+        punchInSettlementService.batchInsert(addPunchInSettlements);
+
+        // 构造并新增关联信息
+        punchInRecordSettlementRelaService.batchInsert(punchInRecordSettlementRelas);
+
+        // 构造并新增结算任务信息
+        settlementTask.setProcessedSettleNum(addPunchInSettlements.size());
+        settlementTask
+            .setProcessedUnsettleNum(settlementTask.getProcessedNum() - settlementTask.getProcessedSettleNum());
+        settlementTask.setEndTime(new Timestamp(System.currentTimeMillis()));
+        settlementTaskService.update(settlementTask);
+
+        log.info("结算任务结束");
+    }
+}

+ 82 - 0
src/main/java/com/punchsettle/server/utiis/DateUtils.java

@@ -0,0 +1,82 @@
+package com.punchsettle.server.utiis;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 日期工具
+ * @date 2024/11/25 15:51
+ */
+public class DateUtils {
+
+    /**
+     * 获取一周的时间范围
+     * @return 返回日期字符串列表
+     */
+    public static List<LocalDate> getWeeklyDateRange() {
+        LocalDate today = LocalDate.now();
+
+        // 获取本周的第一天(假设周一为一周的第一天)
+        LocalDate firstDayOfWeek = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+
+        // 打印本周的所有日期
+        List<LocalDate> list = new ArrayList<>(7);
+        for (int i = 0; i < 7; i++) {
+            LocalDate date = firstDayOfWeek.plusDays(i);
+            list.add(date);
+        }
+        return list;
+    }
+
+    /**
+     * 获取昨天的日期
+     * @return
+     */
+    public static LocalDate getYesterdayDate() {
+        LocalDate today = LocalDate.now();
+        return today.minusDays(1);
+    }
+
+    /**
+     * 获取昨天的日期(字符串)
+     * @return
+     */
+    public static String getYesterdayDateStr() {
+        return getYesterdayDate().toString();
+    }
+
+    /**
+     * 获取上周的周一日期
+     * @return
+     */
+    public static LocalDate getLastWeekMonday() {
+        // 获取当前日期
+        LocalDate today = LocalDate.now();
+        // 获取上周的周一日期
+        return today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusWeeks(1);
+    }
+
+    /**
+     * 获取上周的周一日期(字符串)
+     * @return
+     */
+    public static String getLastWeekMondayStr() {
+        // 获取当前日期
+        LocalDate today = LocalDate.now();
+        // 获取上周的周一日期
+        return today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusWeeks(1).toString();
+    }
+
+    /**
+     * 获取上周的周日日期(字符串)
+     * @return
+     */
+    public static String getLastWeekSundayStr() {
+        return getLastWeekMonday().plusDays(6).toString();
+    }
+}

+ 3 - 3
src/main/java/com/punchsettle/server/utiis/TokenUtils.java

@@ -1,14 +1,14 @@
 package com.punchsettle.server.utiis;
 package com.punchsettle.server.utiis;
 
 
+import java.util.Date;
+import java.util.Map;
+
 import com.auth0.jwt.JWT;
 import com.auth0.jwt.JWT;
 import com.auth0.jwt.JWTVerifier;
 import com.auth0.jwt.JWTVerifier;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.auth0.jwt.interfaces.Claim;
 import com.auth0.jwt.interfaces.Claim;
 import com.punchsettle.server.core.config.BizConfig;
 import com.punchsettle.server.core.config.BizConfig;
 
 
-import java.util.Date;
-import java.util.Map;
-
 /**
 /**
  * @className JwtUtils
  * @className JwtUtils
  * @description Token凭证工具
  * @description Token凭证工具

+ 28 - 0
src/main/java/com/punchsettle/server/utiis/UserUtils.java

@@ -0,0 +1,28 @@
+package com.punchsettle.server.utiis;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2024/11/25 10:15
+ * @description 用户信息相关工具类
+ */
+public class UserUtils {
+
+    public static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();
+
+    /**
+     * 设置当前用户的ID
+     * @param id
+     */
+    public static void setCurrentId(Long id) {
+        threadLocal.set(id);
+    }
+
+    /**
+     * 获取当前用户的ID
+     * @return
+     */
+    public static Long getCurrentUserId() {
+        return threadLocal.get();
+    }
+}

+ 12 - 0
src/main/resources/application-dev.yaml

@@ -0,0 +1,12 @@
+spring:
+  datasource:
+    username: root
+    url: jdbc:mysql://localhost:3306/punch_settle?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
+
+logging:
+  level:
+    com.punchsettle.server: debug
+
+biz:
+  token:
+    password: 12123

+ 8 - 0
src/main/resources/application-prod.yaml

@@ -0,0 +1,8 @@
+spring:
+  datasource:
+#    username: root
+#    url: url=jdbc:mysql://localhost:3306/punch_settle?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
+
+biz:
+  token:
+    password: 12123

+ 2 - 8
src/main/resources/application.yaml

@@ -1,20 +1,15 @@
 server:
 server:
   port: 8080
   port: 8080
-
 spring:
 spring:
+  profiles:
+    active: prod
   application:
   application:
     name: punch-settle-server
     name: punch-settle-server
   datasource:
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    url: jdbc:mysql://localhost:3306/punch_settle?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
   cache:
   cache:
     type: caffeine
     type: caffeine
 
 
-logging:
-  level:
-    com.punchsettle.server: debug
-
 biz:
 biz:
   wechat:
   wechat:
     mini-program:
     mini-program:
@@ -23,4 +18,3 @@ biz:
       secret: ENC(i2ZFfTtFRvAUqpXSW4CQd6HEAMTc0Ltc1dVbhDiIxe4a5H7BbTV3bfiGhFvtRszOMIgyQDoxeZI=)
       secret: ENC(i2ZFfTtFRvAUqpXSW4CQd6HEAMTc0Ltc1dVbhDiIxe4a5H7BbTV3bfiGhFvtRszOMIgyQDoxeZI=)
   token:
   token:
     expire: 7
     expire: 7
-    password: 12123