Browse Source

Merge branch 'fu-dev' of uskycloud/usky-modules into master

gez 2 months ago
parent
commit
881a2a13fb
41 changed files with 3022 additions and 75 deletions
  1. 3 0
      pom.xml
  2. 13 72
      service-oa/service-oa-biz/pom.xml
  3. 0 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/MybatisGeneratorUtils.java
  4. 0 2
      service-oa/service-oa-biz/src/main/java/com/usky/oa/ServiceOaApplication.java
  5. 108 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/MybatisGeneratorUtils.java
  6. 80 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaApprovalController.java
  7. 91 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaDocumentController.java
  8. 95 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaFormDefinitionController.java
  9. 44 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaJbdDocumentController.java
  10. 49 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaQjdDocumentController.java
  11. 100 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaApproval.java
  12. 86 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaDocument.java
  13. 135 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaFormDefinition.java
  14. 118 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaJbdDocument.java
  15. 120 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaQjdDocument.java
  16. 18 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaApprovalMapper.java
  17. 34 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaDocumentMapper.java
  18. 18 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaFormDefinitionMapper.java
  19. 18 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaJbdDocumentMapper.java
  20. 18 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaQjdDocumentMapper.java
  21. 48 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaApprovalService.java
  22. 80 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaDocumentService.java
  23. 72 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaFormDefinitionService.java
  24. 46 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaJbdDocumentService.java
  25. 45 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaQjdDocumentService.java
  26. 49 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/enums/OaBuiltInDocument.java
  27. 195 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaApprovalServiceImpl.java
  28. 235 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaDocumentServiceImpl.java
  29. 331 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaFormDefinitionServiceImpl.java
  30. 188 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaJbdDocumentServiceImpl.java
  31. 217 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaQjdDocumentServiceImpl.java
  32. 33 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/utils/OaDefinitionDocumentInfo.java
  33. 72 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/utils/OaSendMessageCenter.java
  34. 54 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/vo/OaApprovalCountVO.java
  35. 23 0
      service-oa/service-oa-biz/src/main/java/com/usky/oa/service/vo/OaFormNameResponseVO.java
  36. 1 1
      service-oa/service-oa-biz/src/main/resources/bootstrap.yml
  37. 23 0
      service-oa/service-oa-biz/src/main/resources/mapper/oa/OaApprovalMapper.xml
  38. 81 0
      service-oa/service-oa-biz/src/main/resources/mapper/oa/OaDocumentMapper.xml
  39. 30 0
      service-oa/service-oa-biz/src/main/resources/mapper/oa/OaFormDefinitionMapper.xml
  40. 26 0
      service-oa/service-oa-biz/src/main/resources/mapper/oa/OaJbdDocumentMapper.xml
  41. 25 0
      service-oa/service-oa-biz/src/main/resources/mapper/oa/OaQjdDocumentMapper.xml

+ 3 - 0
pom.xml

@@ -87,6 +87,9 @@
 
     <module>service-eg</module>
 
+
+    <module>service-oa</module>
+
   </modules>
           
   

+ 13 - 72
service-oa/service-oa-biz/pom.xml

@@ -14,79 +14,21 @@
             <artifactId>common-cloud-starter</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>com.usky</groupId>
-            <artifactId>service-backend-api</artifactId>
-            <version>0.0.1</version>
-        </dependency>
-
         <dependency>
             <groupId>com.usky</groupId>
             <artifactId>service-oa-api</artifactId>
             <version>0.0.1</version>
         </dependency>
 
-        <dependency>
-            <groupId>cn.afterturn</groupId>
-            <artifactId>easypoi-spring-boot-starter</artifactId>
-            <version>4.1.0</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>aliyun-java-sdk-core</artifactId>
-            <version>4.5.16</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
-            <version>1.1.0</version>
-        </dependency>
-
-        <!--MQTT依赖-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-integration</artifactId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
         </dependency>
-
+        <!-- Pagehelper -->
         <dependency>
-            <groupId>org.springframework.integration</groupId>
-            <artifactId>spring-integration-mqtt</artifactId>
-        </dependency>
-        <!--websocket依赖-->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-websocket</artifactId>
-            <version>5.2.8.RELEASE</version>
-        </dependency>
-        <dependency>
-            <groupId>com.usky</groupId>
-            <artifactId>service-agbox-api</artifactId>
-            <version>0.0.1</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.usky</groupId>
-            <artifactId>service-system-api</artifactId>
-            <version>0.0.1</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.binarywang</groupId>
-            <artifactId>weixin-java-mp</artifactId>
-            <version>4.3.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-amqp</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.usky</groupId>
-            <artifactId>service-alarm-api</artifactId>
-            <version>0.0.1</version>
-            <scope>compile</scope>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
         </dependency>
 
         <dependency>
@@ -94,18 +36,17 @@
             <artifactId>ruoyi-common-core</artifactId>
         </dependency>
 
-        <!--钉钉-->
-        <!--获取企业accessToken(企业内部应用) 新版SDK-->
         <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>dingtalk</artifactId>
-            <version>2.1.34</version>
+        <groupId>com.usky</groupId>
+        <artifactId>service-system-api</artifactId>
+        <version>0.0.1</version>
         </dependency>
-        <!--旧版SDK-->
+
+        <!-- Excel & Word 工具 -->
         <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
-            <version>2.0.0</version>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-spring-boot-starter</artifactId>
+            <version>4.1.0</version>
         </dependency>
 
     </dependencies>

+ 0 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/MybatisGeneratorUtils.java


+ 0 - 2
service-oa/service-oa-biz/src/main/java/com/usky/oa/ServiceOaApplication.java

@@ -3,7 +3,6 @@ import io.swagger.annotations.SwaggerDefinition;
 import org.mybatis.spring.annotation.MapperScan;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.amqp.rabbit.annotation.EnableRabbit;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.openfeign.EnableFeignClients;
@@ -24,7 +23,6 @@ import java.net.UnknownHostException;
 @MapperScan(value = "com.usky.oa.mapper")
 @ComponentScan("com.usky")
 @SpringBootApplication
-@EnableRabbit
 public class ServiceOaApplication
 {
     private static final Logger LOGGER = LoggerFactory.getLogger(ServiceOaApplication.class);

+ 108 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/MybatisGeneratorUtils.java

@@ -0,0 +1,108 @@
+package com.usky.oa.controller;// package com.usky.iot.controller;//package com.usky.dm.controller.web.business;//package com.usky.dm.controller.web;
+
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author yq
+ * @date 2021/7/6 11:42
+ */
+public class MybatisGeneratorUtils {
+    public static void main(String[] args) {
+
+        shell("service-oa", "service-oa-biz");
+    }
+
+    private static void shell(String parentName, String model) {
+
+        AutoGenerator mpg = new AutoGenerator();
+        // 1、全局配置
+        GlobalConfig gc = new GlobalConfig();
+//        File file = new File(model);
+//        String path = file.getAbsolutePath();
+        String projectPath = System.getProperty("user.dir");
+        projectPath += "/" + parentName;
+        projectPath += "/" + model;
+        gc.setOutputDir(projectPath + "/src/main/java");  // 生成路径(一般都是生成在此项目的src/main/java下面)
+        // 修改为自己的名字
+        gc.setAuthor("fu"); // 设置作者
+        gc.setOpen(false);
+        gc.setFileOverride(true); // 第二次生成会把第一次生成的覆盖掉
+        gc.setServiceName("%sService"); // 生成的service接口名字首字母是否为I,这样设置就没有
+        gc.setBaseResultMap(true); // 生成resultMap
+        mpg.setGlobalConfig(gc);
+
+        // 2、数据源配置
+        // 修改数据源
+        DataSourceConfig dsc = new DataSourceConfig();
+        dsc.setUrl("jdbc:mysql://192.168.10.165:3306/usky-cloud?useUnicode=true&serverTimezone=GMT&useSSL=false&characterEncoding=utf8");
+        dsc.setDriverName("com.mysql.jdbc.Driver");
+        dsc.setUsername("root");
+        dsc.setPassword("yt123456");
+        mpg.setDataSource(dsc);
+
+        // 3、包配置
+        PackageConfig pc = new PackageConfig();
+        pc.setParent("com.usky.oa");
+        pc.setController("controller.web");
+        pc.setEntity("domain");
+        pc.setMapper("mapper");
+        pc.setService("service");
+        pc.setServiceImpl("service.impl");
+//        pc.setXml("mapper.demo");
+        // pc.setModuleName("test");
+        mpg.setPackageInfo(pc);
+
+        // 4、策略配置
+        StrategyConfig strategy = new StrategyConfig();
+        strategy.setNaming(NamingStrategy.underline_to_camel);
+        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+        strategy.setSuperMapperClass("com.usky.common.mybatis.core.CrudMapper");
+        strategy.setSuperServiceClass("com.usky.common.mybatis.core.CrudService");
+        strategy.setSuperServiceImplClass("com.usky.common.mybatis.core.AbstractCrudService");
+        // strategy.setTablePrefix("t_"); // 表名前缀
+        strategy.setEntityLombokModel(true); // 使用lombok
+        // 修改自己想要生成的表
+        strategy.setInclude("oa_jb_document");  // 逆向工程使用的表   如果要生成多个,这里可以传入String[]
+        mpg.setStrategy(strategy);
+
+        // 关闭默认 xml 生成,调整生成 至 根目录
+        // 修改对应的模块名称
+        TemplateConfig tc = new TemplateConfig();
+        // 自定义配置
+        InjectionConfig cfg = new InjectionConfig() {
+            @Override
+            public void initMap() {
+                // to do nothing
+            }
+        };
+        // 如果模板引擎是 velocity
+        String templatePath = "/templates/mapper.xml.vm";
+        // 自定义输出配置
+        List<FileOutConfig> focList = new ArrayList<>();
+        // 自定义配置会被优先输出
+        String finalProjectPath = projectPath;
+        focList.add(new FileOutConfig(templatePath) {
+            @Override
+            public String outputFile(TableInfo tableInfo) {
+                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+                return finalProjectPath + "/src/main/resources/mapper/oa" + "/"
+                        + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+            }
+        });
+        cfg.setFileOutConfigList(focList);
+        mpg.setCfg(cfg);
+        tc.setXml(null);
+        mpg.setTemplate(tc);
+        // 5、执行
+        mpg.execute();
+    }
+}

+ 80 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaApprovalController.java

@@ -0,0 +1,80 @@
+package com.usky.oa.controller.web;
+
+
+import com.usky.common.core.bean.CommonPage;
+import com.usky.oa.domain.OaApproval;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.service.OaApprovalService;
+import com.usky.oa.service.vo.OaApprovalCountVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import org.springframework.stereotype.Controller;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 审批表 前端控制器
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@RestController
+@RequestMapping("/oaApproval")
+public class OaApprovalController {
+
+    @Autowired
+    private OaApprovalService oaApprovalService;
+
+    /**
+     * @description: 审批数量统计
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/30 16:19
+     * @param: []
+     * @return: void
+     **/
+    @GetMapping("/count")
+    public OaApprovalCountVO approvalCount() {
+        return oaApprovalService.approvalCount();
+    }
+
+    /**
+     * @description: 我的待办-分页列表
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/30 16:19
+     * @param: [queryType, docNo, type, approvalStatus, startTime, endTime, pageNum, pageSize]
+     * @return: com.usky.common.core.bean.CommonPage<com.usky.oa.domain.OaApproval>
+     **/
+    @GetMapping("/pageList")
+    public CommonPage<OaApproval> pageList(@RequestParam(value = "queryType") Integer queryType,
+                                           @RequestParam(value = "docNo", required = false) String docNo,
+                                           @RequestParam(value = "formSign", required = false) String formSign,
+                                           @RequestParam(value = "approvalStatus", required = false) Integer approvalStatus,
+                                           @RequestParam(value = "startTime", required = false) String startTime,
+                                           @RequestParam(value = "endTime", required = false) String endTime,
+                                           @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
+                                           @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
+        return oaApprovalService.pageList(queryType, docNo, formSign, approvalStatus, startTime, endTime, pageNum, pageSize);
+    }
+
+    /**
+     * @description: 审批
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/17 17:32
+     * @param: [oaApproval]
+     * @return: void
+     **/
+    @PutMapping("/approve")
+    public void add(@RequestParam(value = "id") Integer id,
+                    @RequestParam(value = "approvalStatus") Integer approvalStatus,
+                    @RequestParam(value = "opinion", required = false, defaultValue = "无") String opinion) {
+        oaApprovalService.approve(id, approvalStatus, opinion);
+    }
+
+}
+

+ 91 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaDocumentController.java

@@ -0,0 +1,91 @@
+package com.usky.oa.controller.web;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.log.annotation.Log;
+import com.usky.common.log.enums.BusinessType;
+import com.usky.common.mybatis.core.CrudService;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.service.OaDocumentService;
+import com.usky.oa.service.vo.OaApprovalCountVO;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import org.springframework.stereotype.Controller;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 单据总表 前端控制器
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-26
+ */
+@RestController
+@RequestMapping("/oaDocument")
+public class OaDocumentController {
+
+    @Autowired
+    private OaDocumentService oaDocumentService;
+
+    // 我的申请
+    @GetMapping("/myApplication")
+    public CommonPage<OaDocument> myApplication(@RequestParam(value = "docNo", required = false) String docNo,
+                                                @RequestParam(value = "type", required = false) String type,
+                                                @RequestParam(value = "docStatus", required = false) Integer status,
+                                                @RequestParam(value = "startTime", required = false) String startTime,
+                                                @RequestParam(value = "endTime", required = false) String endTime,
+                                                @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
+                                                @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
+        return oaDocumentService.myApplication(docNo, type, status, startTime, endTime, pageNum, pageSize);
+    }
+
+    /**
+     * @description: 新增单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/17 14:19
+     * @param: [oaDocument]
+     * @return: void
+     **/
+    @Log(title = "新增单据", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    public void addDocument(@RequestBody JSONObject oaDocument) {
+        oaDocumentService.addDoc(oaDocument);
+    }
+
+    // 删除单据
+    @Log(title = "删除单据", businessType = BusinessType.DELETE)
+    @DeleteMapping("/delDoc/{docNo}")
+    public void delDocument(@PathVariable(value = "docNo") String docNo) {
+        oaDocumentService.delDocument(docNo);
+    }
+
+    // 单据详情
+    @GetMapping("/documentDetails")
+    public Object documentDetails(@RequestParam(value = "docNo") String docNo) {
+        return oaDocumentService.documentDetails(docNo);
+    }
+
+    // 更新单据
+    @Log(title = "更新单据", businessType = BusinessType.UPDATE)
+    @PostMapping("/update")
+    public void approvalCount(@RequestBody JSONObject jsonDocument) {
+        oaDocumentService.updateDoc(jsonDocument);
+    }
+
+    // 提交单据
+    @Log(title = "提交单据", businessType = BusinessType.UPDATE)
+    @PutMapping("/submit")
+    public void submit(@RequestParam(value = "docNo") String docNo,
+                       @RequestParam(value = "docStatus") Integer docStatus){
+        oaDocumentService.submit(docNo, docStatus);
+    }
+
+}
+

+ 95 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaFormDefinitionController.java

@@ -0,0 +1,95 @@
+package com.usky.oa.controller.web;
+
+
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.log.annotation.Log;
+import com.usky.common.log.enums.BusinessType;
+import com.usky.oa.domain.OaFormDefinition;
+import com.usky.oa.service.OaFormDefinitionService;
+import com.usky.oa.service.enums.OaBuiltInDocument;
+import com.usky.oa.service.utils.OaDefinitionDocumentInfo;
+import com.usky.oa.service.vo.OaFormNameResponseVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 表单定义表 前端控制器
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@RestController
+@RequestMapping("/oaFormDefinition")
+public class OaFormDefinitionController {
+
+    @Autowired
+    private OaFormDefinitionService oaFormDefinitionService;
+
+    // 新增、修改表单
+    @Log(title = "新增/修改表单", businessType = BusinessType.INSERT)
+    @PostMapping("/addForm")
+    public void addForm(@RequestBody OaFormDefinition oaFormDefinition) {
+        oaFormDefinitionService.addForm(oaFormDefinition);
+    }
+
+    // 表单状态修改(启用、停用)
+    @Log(title = "启停用表单", businessType = BusinessType.UPDATE)
+    @GetMapping("/updateStatus")
+    public void updateStatus(@RequestParam(value = "formId") Integer formId,
+                             @RequestParam(value = "formStatus") Integer formStatus) {
+        oaFormDefinitionService.validUpdateStatus(formId, formStatus);
+    }
+
+    // 删除表单
+    @Log(title = "删除表单", businessType = BusinessType.DELETE)
+    @DeleteMapping("/delForm/{formId}")
+    public void delForm(@PathVariable Integer formId) {
+        oaFormDefinitionService.delForm(formId);
+    }
+
+    // 表单管理-分页
+    @GetMapping("/manageForm")
+    public ApiResult<CommonPage<OaFormDefinition>> manageForm(@RequestParam(value = "formName", required = false) String formName,
+                                                              @RequestParam(value = "formId", required = false) Integer formId,
+                                                              @RequestParam(value = "formGroup", required = false) Integer formGroup,
+                                                              @RequestParam(value = "formStatus", required = false) Integer formStatus,
+                                                              @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
+                                                              @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
+        return ApiResult.success(oaFormDefinitionService.pageList(formId, formName, formGroup, formStatus, pageNum, pageSize));
+    }
+
+    // 内置单据枚举列表
+    @GetMapping("/builtInFormEnums")
+    public List<OaDefinitionDocumentInfo> getBuiltInDocumentList(String sign, String name) {
+        return Arrays.stream(OaBuiltInDocument.values())
+                .map(doc -> new OaDefinitionDocumentInfo(doc.getSign(), doc.getName()))
+                .filter(docInfo -> (sign == null || docInfo.getSign().equals(sign))
+                        && (name == null || docInfo.getName().contains(name)))
+                .collect(Collectors.toList());
+    }
+
+    // 我的申请-依据权限展示表单
+    @GetMapping("/myForm")
+    public List<OaFormDefinition> myForm(String formSign) {
+        return oaFormDefinitionService.selectByScope(formSign);
+    }
+
+    // 表单名称列表
+    @GetMapping("/getFormName")
+    public List<OaFormNameResponseVO> getFormName(@RequestParam(value = "formSign", required = false) String formSign,
+                                                  @RequestParam(value = "formName", required = false) String formName,
+                                                  @RequestParam(value = "formId", required = false) Integer formId) {
+        return oaFormDefinitionService.getFormName(formSign, formName, formId);
+    }
+
+
+}
+

+ 44 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaJbdDocumentController.java

@@ -0,0 +1,44 @@
+package com.usky.oa.controller.web;
+
+
+import com.usky.common.log.annotation.Log;
+import com.usky.common.log.enums.BusinessType;
+import com.usky.oa.domain.OaJbdDocument;
+import com.usky.oa.service.OaJbdDocumentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * <p>
+ * 加班单据表 前端控制器
+ * </p>
+ *
+ * @author fu
+ * @since 2025-01-02
+ */
+@RestController
+@RequestMapping("/oaJbDocument")
+public class OaJbdDocumentController {
+
+    @Autowired
+    private OaJbdDocumentService oaJbdDocumentService;
+
+    @Log(title = "新增加班单", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    public void addJbDocument(@RequestBody OaJbdDocument oaJbdDocument) {
+        oaJbdDocumentService.add(oaJbdDocument);
+    }
+
+    @Log(title = "更新加班单", businessType = BusinessType.UPDATE)
+    @PostMapping("/update")
+    public void updateJbDocument(OaJbdDocument oaJbdDocument) {
+        oaJbdDocumentService.update(oaJbdDocument);
+    }
+
+    @Log(title = "删除加班单", businessType = BusinessType.DELETE)
+    @DeleteMapping("/del/{docNo}")
+    public void delJbDocument(@PathVariable String docNo) {
+        oaJbdDocumentService.delByDocNo(docNo);
+    }
+
+}

+ 49 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/controller/web/OaQjdDocumentController.java

@@ -0,0 +1,49 @@
+package com.usky.oa.controller.web;
+
+
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.log.annotation.Log;
+import com.usky.common.log.enums.BusinessType;
+import com.usky.oa.domain.OaQjdDocument;
+import com.usky.oa.service.OaQjdDocumentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * <p>
+ * 请假单据表 前端控制器
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@RestController
+@RequestMapping("/oaQjDocument")
+public class OaQjdDocumentController {
+
+    @Autowired
+    private OaQjdDocumentService oaQjdDocumentService;
+
+    // 新增请假单
+    @Log(title = "新增请假单", businessType = BusinessType.INSERT)
+    @PostMapping("/addQjDocument")
+    public void addQjDocument(@RequestBody OaQjdDocument oaQjdDocument) {
+        oaQjdDocumentService.addQjDocument(oaQjdDocument);
+    }
+
+    // 更新请假单
+    @Log(title = "更新请假单", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateQjDocument")
+    public void updateQjDocument(@RequestBody OaQjdDocument oaQjdDocument) {
+        oaQjdDocumentService.updateQjDocument(oaQjdDocument);
+    }
+
+    // 删除请假单
+    @Log(title = "删除请假单", businessType = BusinessType.DELETE)
+    @DeleteMapping("/delQjDocument/{docNo}")
+    public void delQjDocument(String docNo) {
+        oaQjdDocumentService.delQjDocument(docNo);
+    }
+
+}

+ 100 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaApproval.java

@@ -0,0 +1,100 @@
+package com.usky.oa.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 审批表
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class OaApproval implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 审批表主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 单据编号
+     */
+    private String docNo;
+
+    /**
+     * 审批人id
+     */
+    private Long approvalUid;
+
+    /**
+     * 审批类型(0:审批,1:知会)
+     */
+    private Integer type;
+
+    /**
+     * 审批状态(1:审批中, 2:审批通过, 3:审批不通过)
+     */
+    private Integer approvalStatus;
+
+    /**
+     * 审批意见
+     */
+    private String opinion;
+
+    /**
+     * 提交时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime submitDate;
+
+    /**
+     * 审批时间
+     */
+    private LocalDateTime approvalDate;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+
+}

+ 86 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaDocument.java

@@ -0,0 +1,86 @@
+package com.usky.oa.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 单据总表
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class OaDocument implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 单据总表主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 表单定义表主键
+     */
+    private Integer formId;
+
+    /**
+     * 表单标识
+     */
+    private String type;
+
+    /**
+     * 单据编号
+     */
+    private String docNo;
+
+    /**
+     * 申请人id
+     */
+    private Long proposer;
+
+    /**
+     * 单据状态 (0:未提交可以修改,1:审批中,2:审批通过,3:审批不通过)
+     */
+    private Integer docStatus;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+
+}

+ 135 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaFormDefinition.java

@@ -0,0 +1,135 @@
+package com.usky.oa.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 表单定义表
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class OaFormDefinition implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 表单定义表主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 表单名称
+     */
+    private String formName;
+
+    /**
+     * 所在分组
+     */
+    private Integer formGroup;
+
+    /**
+     * 表单说明
+     */
+    private String formExplain;
+
+    /**
+     * 单据类型(0:内置表单据;1:自定义表单据)
+     */
+    private Integer formType;
+
+    /**
+     * 表单设计器配置数据
+     */
+    private String fieldInfo;
+
+    /**
+     * 流程设计器配置数据
+     */
+    private String flowInfo;
+
+    /**
+     * 表单版本
+     */
+    private Integer formVersion;
+
+    /**
+     * 表单标识(必须字母,小于4位)
+     */
+    private String formSign;
+
+    /**
+     * 表单图标
+     */
+    private String formImage;
+
+    /**
+     * 表单权限范围(0:指定部门可见;1:全员可见;2:指定人可见)
+     */
+    private Integer formScope;
+
+    /**
+     * 表单状态(1:启用;2:停用)
+     */
+    private Integer formStatus;
+
+    /*
+     * 单据编号
+     */
+    //private Integer docNo;
+
+    /**
+     * 可见部门id集合
+     */
+    private String deptIds;
+
+    /**
+     * 可见人id集合
+     */
+    private String userIds;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+
+}

+ 118 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaJbdDocument.java

@@ -0,0 +1,118 @@
+package com.usky.oa.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 加班单据表
+ * </p>
+ *
+ * @author fu
+ * @since 2025-01-02
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class OaJbdDocument implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 加班单据表主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 表单定义表主键
+     */
+    private Integer formId;
+
+    /**
+     * 单据编号
+     */
+    private String docNo;
+
+    /**
+     * 申请人id
+     */
+    private Long proposer;
+
+    /**
+     * 单据状态 (0:未提交可以修改,1:审批中,2:审批通过,3:审批不通过,4:撤销)
+     */
+    private Integer docStatus;
+
+    /**
+     * 开始日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    /**
+     * 结束日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
+
+    /**
+     * 加班时长(小时)
+     */
+    private Integer duration;
+
+    /**
+     * 核算方式(默认 0:申请调休)
+     */
+    private Integer accountingMethod;
+
+    /**
+     * 加班原因
+     */
+    private String reason;
+
+    /**
+     * 图片URL(打卡记录及日报)
+     */
+    private String image;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+
+}

+ 120 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/domain/OaQjdDocument.java

@@ -0,0 +1,120 @@
+package com.usky.oa.domain;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 请假单据表
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class OaQjdDocument implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 请假单据表主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 表单id
+     */
+    private Integer formId;
+
+    /**
+     * 1:事假,2:病假(后续附上病假单、挂号单、病历册),3:年假(连续在我司工作一年以上的,才可享受),4:调休(有已获批准的加班流程),
+     * 5:婚假(附上结婚证),6:产假(后续附上出生证明),7:陪产假(后续附上出生证明),8:丧假(父母、配偶、子女死亡可申请3天),9:工伤假,
+     * 10:孕检假(后续附上挂号单、病例册)
+     */
+    private String type;
+
+    /**
+     * 单据编号
+     */
+    private String docNo;
+
+    /**
+     * 申请人id
+     */
+    private Long proposer;
+
+    /**
+     * 单据状态 (0:未提交可以修改,1:审批中,2:审批通过,3:审批不通过,4:撤销)
+     */
+    private Integer docStatus;
+
+    /**
+     * 开始日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    /**
+     * 结束日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
+
+    /**
+     * 请假时长(小时)
+     */
+    private Integer duration;
+
+    /**
+     * 请假事由
+     */
+    private String reason;
+
+    /**
+     * 图片URL
+     */
+    private String image;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+
+}

+ 18 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaApprovalMapper.java

@@ -0,0 +1,18 @@
+package com.usky.oa.mapper;
+
+import com.usky.oa.domain.OaApproval;
+import com.usky.common.mybatis.core.CrudMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * <p>
+ * 审批表 Mapper 接口
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Repository
+public interface OaApprovalMapper extends CrudMapper<OaApproval> {
+
+}

+ 34 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaDocumentMapper.java

@@ -0,0 +1,34 @@
+package com.usky.oa.mapper;
+
+import com.usky.oa.domain.OaDocument;
+import com.usky.common.mybatis.core.CrudMapper;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * <p>
+ * 单据总表 Mapper 接口
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-26
+ */
+public interface OaDocumentMapper extends CrudMapper<OaDocument> {
+
+    // 动态创建表
+    void createTable(Map<String, Object> params);
+
+    // 动态插入数据
+    void insertData(Map<String, Object> params);
+
+    // 动态查询数据
+    List<Map<String, Object>> selectData(Map<String, Object> params);
+
+    // 动态更新数据
+    void updateData(Map<String, Object> params);
+
+    // 动态删除数据
+    void deleteData(Map<String, Object> params);
+}

+ 18 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaFormDefinitionMapper.java

@@ -0,0 +1,18 @@
+package com.usky.oa.mapper;
+
+import com.usky.oa.domain.OaFormDefinition;
+import com.usky.common.mybatis.core.CrudMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * <p>
+ * 表单定义表 Mapper 接口
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Repository
+public interface OaFormDefinitionMapper extends CrudMapper<OaFormDefinition> {
+
+}

+ 18 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaJbdDocumentMapper.java

@@ -0,0 +1,18 @@
+package com.usky.oa.mapper;
+
+import com.usky.oa.domain.OaJbdDocument;
+import com.usky.common.mybatis.core.CrudMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * <p>
+ * 加班单据表 Mapper 接口
+ * </p>
+ *
+ * @author fu
+ * @since 2025-01-02
+ */
+@Repository
+public interface OaJbdDocumentMapper extends CrudMapper<OaJbdDocument> {
+
+}

+ 18 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/mapper/OaQjdDocumentMapper.java

@@ -0,0 +1,18 @@
+package com.usky.oa.mapper;
+
+import com.usky.oa.domain.OaQjdDocument;
+import com.usky.common.mybatis.core.CrudMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * <p>
+ * 请假单据表 Mapper 接口
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Repository
+public interface OaQjdDocumentMapper extends CrudMapper<OaQjdDocument> {
+
+}

+ 48 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaApprovalService.java

@@ -0,0 +1,48 @@
+package com.usky.oa.service;
+
+import com.usky.common.core.bean.CommonPage;
+import com.usky.oa.domain.OaApproval;
+import com.usky.common.mybatis.core.CrudService;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.service.vo.OaApprovalCountVO;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 审批表 服务类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+public interface OaApprovalService extends CrudService<OaApproval> {
+
+    /**
+     * 审批统计
+     * @return OaApprovalCountVO
+     */
+    OaApprovalCountVO approvalCount();
+
+    /**
+     * 审批列表
+     * @param queryType 查询类型(1:待处理,2:已处理,3:我收到)
+     * @param docNo 单据编号
+     * @param formSign 单据类型(请假申请-QJD...按标识查询)
+     * @param approvalStatus 审批状态(1:审批中,2:审批通过,3:审批不通过)
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @param pageNum 页码
+     * @param pageSize 页大小
+     * @return CommonPage<OaApproval>
+     */
+    CommonPage<OaApproval> pageList(Integer queryType, String docNo, String formSign, Integer approvalStatus, String startTime, String endTime, Integer pageNum, Integer pageSize);
+
+    /**
+     * 审批
+     * @param id 审批ID
+     * @param approvalStatus 审批状态(1:审批中,2:审批通过,3:审批不通过)
+     */
+    void approve(Integer id, Integer approvalStatus, String opinion);
+}

+ 80 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaDocumentService.java

@@ -0,0 +1,80 @@
+package com.usky.oa.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.oa.domain.OaDocument;
+import com.usky.common.mybatis.core.CrudService;
+import com.usky.oa.service.vo.OaApprovalCountVO;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 单据总表 服务类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-26
+ */
+public interface OaDocumentService extends CrudService<OaDocument> {
+
+    /**
+     * @description: 我的申请
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/31 13:17
+     * @param: []
+     * @return: java.util.List<com.usky.oa.domain.OaDocument>
+     **/
+    CommonPage<OaDocument> myApplication(String docNo, String type, Integer status, String startTime, String endTime, Integer pageNum, Integer pageSize);
+
+    /**
+     * @description: 单据详情
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/31 13:17
+     * @param: []
+     * @return: java.util.List<com.usky.oa.domain.OaDocument>
+     **/
+    Object documentDetails(String docNo);
+
+    /**
+     * @description: 删除单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/31 13:17
+     * @param: []
+     * @return: java.util.List<com.usky.oa.domain.OaDocument>
+     **/
+    void delDocument(String docNo);
+
+    /**
+     * @description: 新增单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/6 16:32
+     * @param: [oaDocument]
+     * @return: void
+     **/
+    void addDoc(JSONObject oaDocument);
+
+    /**
+     * @description: 修改单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/6 16:34
+     * @param: [oaDocument]
+     * @return: com.usky.oa.domain.OaDocument
+     **/
+    void updateDoc(JSONObject jsonDocument);
+
+    /**
+     * @description: 提交单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/6 16:34
+     * @param: [docNo]
+     * @return: void
+     **/
+    void submit(String docNo, Integer docStatus);
+}

+ 72 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaFormDefinitionService.java

@@ -0,0 +1,72 @@
+package com.usky.oa.service;
+
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.log.annotation.Log;
+import com.usky.common.log.enums.BusinessType;
+import com.usky.oa.domain.OaFormDefinition;
+import com.usky.common.mybatis.core.CrudService;
+import com.usky.oa.service.vo.OaFormNameResponseVO;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 表单定义表 服务类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+public interface OaFormDefinitionService extends CrudService<OaFormDefinition> {
+
+    /**
+     * 新增/更新 表单
+     * @param oaFormDefinition
+     */
+    void addForm(OaFormDefinition oaFormDefinition);
+
+    /**
+     * 删除表单
+     * @param formId
+     */
+    void delForm(Integer formId);
+
+    /**
+     * 分页查询表单列表
+     * @param formName 表单名称
+     * @param pageNum 页码
+     * @param pageSize 页大小
+     * @return
+     */
+    CommonPage<OaFormDefinition> pageList(Integer formId, String formName, Integer formGroup, Integer formStatus, Integer pageNum, Integer pageSize);
+
+    /**
+     * 更新表单状态并校验
+     * @param formId
+     * @param formStatus
+     */
+    void validUpdateStatus(Integer formId, Integer formStatus);
+
+    /**
+     * @description: 根据表单标识查询表单信息-数据权限
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/3 14:07
+     * @param: [formSign]
+     * @return: java.util.List<com.usky.oa.domain.OaFormDefinition>
+     **/
+    List<OaFormDefinition> selectByScope(String formSign);
+
+    /**
+     * @description: 获取表单名称列表
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/3 14:07
+     * @param: []
+     * @return: java.util.Map<java.lang.Integer,java.lang.String>
+     **/
+    List<OaFormNameResponseVO> getFormName(String formSign, String formName, Integer formId);
+
+}

+ 46 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaJbdDocumentService.java

@@ -0,0 +1,46 @@
+package com.usky.oa.service;
+
+import com.usky.oa.domain.OaJbdDocument;
+import com.usky.common.mybatis.core.CrudService;
+
+/**
+ * <p>
+ * 加班单据表 服务类
+ * </p>
+ *
+ * @author fu
+ * @since 2025-01-02
+ */
+public interface OaJbdDocumentService extends CrudService<OaJbdDocument> {
+
+    /**
+     * @description: 新增加班单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 14:00
+     * @param: [oaJbDocument]
+     * @return: void
+     **/
+    void add(OaJbdDocument oaJbdDocument);
+
+    /**
+     * @description: 更新加班单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 15:43
+     * @param: [oaJbDocument]
+     * @return: void
+     **/
+    void update(OaJbdDocument oaJbdDocument);
+
+    /**
+     * @description: 删除加班单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 15:43
+     * @param: [id]
+     * @return: void
+     **/
+    void delByDocNo(String docNo);
+
+}

+ 45 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/OaQjdDocumentService.java

@@ -0,0 +1,45 @@
+package com.usky.oa.service;
+
+import com.usky.oa.domain.OaQjdDocument;
+import com.usky.common.mybatis.core.CrudService;
+
+/**
+ * <p>
+ * 请假单据表 服务类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+public interface OaQjdDocumentService extends CrudService<OaQjdDocument> {
+
+    /**
+     * @description: 新增请假单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/26 14:15
+     * @param: [oaQjDocument]
+     * @return: void
+     **/
+    void addQjDocument(OaQjdDocument oaQjdDocument);
+
+    /**
+     * @description: 修改请假单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/26 14:15
+     * @param: [oaQjDocument]
+     * @return: void
+     **/
+    void updateQjDocument(OaQjdDocument oaQjdDocument);
+
+    /**
+     * @description: 删除请假单据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/26 15:20
+     * @param: [id]
+     * @return: void
+     **/
+    void delQjDocument(String docNo);
+}

+ 49 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/enums/OaBuiltInDocument.java

@@ -0,0 +1,49 @@
+package com.usky.oa.service.enums;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2024/12/25
+ */
+public enum OaBuiltInDocument {
+
+    QJD("QJD", "请假单"),
+    JBD("JBD", "加班单");
+    // LZD("LZ", "离职单"),
+    // CCD("CC", "出差单"),
+    // WCD("WC", "外出单"),
+    // BHSQ("BHSQ", "项目编号申请单"),
+    // MPD("MPYS", "名片印刷单"),
+    // JPD("DJP", "机票单"),
+    // GDZC("ZCLY", "固定资产领用单"),
+    // ZZJY("ZZJY", "印章资质借用单"),
+    // HTJY("HTJY", "合同借用单"),
+    // //XMCG("XMCG", "项目采购表单");
+    // // 项目采购;固定资产采购;行政(特殊)用品采购
+    // CGD("CGSQ", "采购单"),
+    // //XZCG("XZCG", "行政(特殊)用品采购表单"),
+    // YYD("YYSQ", "用印申请单");
+
+    private final String sign;
+    private final String name;
+
+    OaBuiltInDocument(String sign, String name) {
+        this.sign = sign;
+        this.name = name;
+    }
+
+    public String getSign() {
+        return sign;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+}

+ 195 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaApprovalServiceImpl.java

@@ -0,0 +1,195 @@
+package com.usky.oa.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.oa.domain.OaApproval;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.mapper.OaApprovalMapper;
+import com.usky.oa.mapper.OaDocumentMapper;
+import com.usky.oa.service.OaApprovalService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.oa.service.vo.OaApprovalCountVO;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * <p>
+ * 审批表 服务实现类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Service
+public class OaApprovalServiceImpl extends AbstractCrudService<OaApprovalMapper, OaApproval> implements OaApprovalService {
+
+    @Autowired
+    private OaApprovalMapper oaApprovalMapper;
+
+    @Autowired
+    private OaDocumentMapper oaDocumentMapper;
+
+    // 我的申请-待处理、已处理、我发起、我收到-统计
+    @Override
+    public OaApprovalCountVO approvalCount() {
+        Long userId = SecurityUtils.getUserId();
+        String username = SecurityUtils.getUsername();
+        Integer tenantId = SecurityUtils.getTenantId();
+
+        OaApprovalCountVO oaApprovalCountVO = new OaApprovalCountVO();
+        // 待处理
+        oaApprovalCountVO.setPendingSum(getPendingSum(tenantId, userId).size());
+        // 已处理
+        oaApprovalCountVO.setAlreadySum(getAlreadySum(tenantId, userId).size());
+        // 我发起
+        oaApprovalCountVO.setMyInitiated(getMyInitiated(tenantId, username).size());
+        // 我收到
+        oaApprovalCountVO.setMyReceived(getMyReceived(tenantId, userId).size());
+
+        return oaApprovalCountVO;
+    }
+
+    // 我的代办-待处理、已处理、我收到-分页
+    @Override
+    public CommonPage<OaApproval> pageList(Integer queryType, String docNo, String formSign, Integer approvalStatus, String startTime, String endTime, Integer pageNum, Integer pageSize) {
+        Long userId = SecurityUtils.getUserId();
+        Integer tenantId = SecurityUtils.getTenantId();
+        IPage<OaApproval> page = new Page<>(pageNum, pageSize);
+
+        LocalDateTime now = LocalDateTime.now();
+        // 一年前时间
+        LocalDateTime oneYearAgo = now.minusYears(1);
+
+        List<Integer> processed = Stream.of(2, 3).collect(Collectors.toList());
+
+        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaApproval::getTenantId, tenantId)
+                .eq(OaApproval::getApprovalUid, userId)
+                .between(OaApproval::getCreateTime, oneYearAgo, now);
+
+        switch (queryType) {
+            case 1:
+                queryWrapper.eq(OaApproval::getApprovalStatus, 1)
+                        .like(StringUtils.isNotBlank(docNo), OaApproval::getDocNo, docNo)
+                        .like(StringUtils.isNotBlank(formSign), OaApproval::getDocNo, formSign)
+                        .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaApproval::getSubmitDate, startTime, endTime);
+                break;
+            case 2:
+                queryWrapper.like(StringUtils.isNotBlank(docNo), OaApproval::getDocNo, docNo)
+                        .like(StringUtils.isNotBlank(formSign), OaApproval::getDocNo, formSign)
+                        .eq(approvalStatus != null && approvalStatus > 1 && approvalStatus < 4, OaApproval::getApprovalStatus, approvalStatus)
+                        .in(OaApproval::getApprovalStatus, processed)
+                        .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaApproval::getSubmitDate, startTime, endTime);
+                break;
+            case 3:
+                queryWrapper.like(StringUtils.isNotBlank(docNo), OaApproval::getDocNo, docNo)
+                        .like(StringUtils.isNotBlank(formSign), OaApproval::getDocNo, formSign)
+                        .eq(OaApproval::getType, 1)
+                        .eq(approvalStatus != null && approvalStatus > 0 && approvalStatus < 4, OaApproval::getApprovalStatus, approvalStatus)
+                        .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaApproval::getSubmitDate, startTime, endTime);
+                break;
+            default:
+                throw new RuntimeException("查询类型参数错误");
+        }
+        return ToCommonPage(oaApprovalMapper.selectPage(page, queryWrapper));
+    }
+
+    // 审批
+    @Override
+    public void approve(Integer id, Integer approvalStatus, String opinion) {
+        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaApproval::getId, id);
+        OaApproval oaApproval = oaApprovalMapper.selectOne(queryWrapper);
+
+        if (!oaApproval.getApprovalUid().equals(SecurityUtils.getUserId())) {
+            throw new BusinessException("审批权限不足,暂时无法更改!");
+        }
+
+        if (oaApproval.getApprovalStatus() != 1) {
+            throw new BusinessException("审批状态异常,暂时无法更改!");
+        }
+        if (approvalStatus < 2 || approvalStatus > 3) {
+            throw new BusinessException("审批类型错误,请重试!");
+        }
+
+        oaApproval.setApprovalStatus(approvalStatus);
+        oaApproval.setOpinion(opinion);
+        oaApproval.setApprovalDate(LocalDateTime.now());
+        oaApproval.setUpdateBy(SecurityUtils.getUsername());
+        oaApproval.setUpdateTime(LocalDateTime.now());
+        oaApprovalMapper.updateById(oaApproval);
+    }
+
+    // 待处理
+    private List<OaApproval> getPendingSum(Integer tenantId, Long userId) {
+        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaApproval::getTenantId, tenantId)
+                .eq(OaApproval::getApprovalUid, userId)
+                .eq(OaApproval::getApprovalStatus, 1);
+        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
+        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
+    }
+
+    // 已处理
+    private List<OaApproval> getAlreadySum(Integer tenantId, Long userId) {
+        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaApproval::getTenantId, tenantId)
+                .eq(OaApproval::getApprovalUid, userId)
+                .and(wrapper -> wrapper
+                        .eq(OaApproval::getApprovalStatus, 2)
+                        .or()
+                        .eq(OaApproval::getApprovalStatus, 3));
+        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
+        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
+    }
+
+    // 我发起
+    /*private List<OaApproval> getMyInitiated(Integer tenantId, String username) {
+        List<String> docNoList = oaDocumentMapper.selectList(new QueryWrapper<OaDocument>().lambda()
+                .select(OaDocument::getDocNo)
+                .eq(OaDocument::getTenantId, tenantId)
+                .eq(OaDocument::getCreateBy, username)
+                // 已发起只计算 审批中、审通过、审批不通过
+                .in(OaDocument::getDocStatus, 1, 2, 3)).stream().map(OaDocument::getDocNo).collect(Collectors.toList());
+
+        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.in(OaApproval::getDocNo, docNoList);
+        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
+        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
+    }*/
+
+    // 我发起
+    private List<OaDocument> getMyInitiated(Integer tenantId, String username) {
+        List<OaDocument> oaDocuments = oaDocumentMapper.selectList(new QueryWrapper<OaDocument>().lambda()
+                .select(OaDocument::getDocNo)
+                .eq(OaDocument::getTenantId, tenantId)
+                .eq(OaDocument::getCreateBy, username));
+        return oaDocuments == null ? Collections.emptyList() : oaDocuments;
+    }
+
+    // 我收到
+    private List<OaApproval> getMyReceived(Integer tenantId, Long userId) {
+        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaApproval::getTenantId, tenantId)
+                .eq(OaApproval::getApprovalUid, userId)
+                .eq(OaApproval::getType, 1);
+        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
+        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
+    }
+
+}

+ 235 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaDocumentServiceImpl.java

@@ -0,0 +1,235 @@
+package com.usky.oa.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.oa.domain.*;
+import com.usky.oa.mapper.*;
+import com.usky.oa.service.OaDocumentService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.oa.service.OaJbdDocumentService;
+import com.usky.oa.service.OaQjdDocumentService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * 单据总表 服务实现类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-26
+ */
+@Service
+public class OaDocumentServiceImpl extends AbstractCrudService<OaDocumentMapper, OaDocument> implements OaDocumentService {
+
+    @Autowired
+    private OaDocumentMapper oaDocumentMapper;
+
+    @Autowired
+    private OaQjdDocumentMapper oaQjdDocumentMapper;
+
+    @Autowired
+    private OaQjdDocumentService oaQjdDocumentService;
+
+    @Autowired
+    private OaJbdDocumentService oaJbdDocumentService;
+
+    @Autowired
+    private OaJbdDocumentMapper oaJbdDocumentMapper;
+
+    @Autowired
+    private OaDocumentMapper documentMapper;
+
+    @Autowired
+    private OaFormDefinitionMapper oaFormDefinitionMapper;
+
+    @Autowired
+    private OaApprovalMapper oaApprovalMapper;
+
+    private static final String TABLE_HEAD = "oa_";
+    private static final String TABLE_SUFFIX = "_document";
+
+    // 我的申请
+    @Override
+    public CommonPage<OaDocument> myApplication(String docNo, String type, Integer status, String startTime, String endTime, Integer pageNum, Integer pageSize) {
+        Long userId = SecurityUtils.getUserId();
+        Integer tenantId = SecurityUtils.getTenantId();
+
+        LambdaQueryWrapper<OaDocument> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(OaDocument::getTenantId, tenantId).eq(OaDocument::getProposer, userId)
+                .like(StringUtils.isNotBlank(docNo), OaDocument::getDocNo, docNo)
+                .eq(StringUtils.isNotBlank(type), OaDocument::getType, type)
+                .eq(status != null, OaDocument::getDocStatus, status)
+                .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaDocument::getCreateTime, startTime, endTime)
+                .orderByDesc(OaDocument::getId);
+
+        return ToCommonPage(page(new Page<>(pageNum, pageSize), wrapper));
+    }
+
+    // 单据详情
+    @Override
+    public Object documentDetails(String docNo) {
+        Object documentDetails = null;
+        String type = getFormSign(docNo);
+
+        switch (type) {
+            case "QJD":
+                documentDetails = oaQjdDocumentMapper.selectOne(Wrappers.lambdaQuery(OaQjdDocument.class).eq(OaQjdDocument::getDocNo, docNo));
+                break;
+            case "JBD":
+                documentDetails = oaJbdDocumentMapper.selectOne(Wrappers.lambdaQuery(OaJbdDocument.class).eq(OaJbdDocument::getDocNo, docNo));
+                break;
+        }
+
+        return documentDetails;
+    }
+
+    // 删除单据
+    @Override
+    public void delDocument(String docNo) {
+        String type = getFormSign(docNo);
+        switch (type) {
+            case "QJD":
+                oaQjdDocumentMapper.delete(Wrappers.lambdaQuery(OaQjdDocument.class).eq(OaQjdDocument::getDocNo, docNo));
+                break;
+            case "JBD":
+                oaJbdDocumentMapper.delete(Wrappers.lambdaQuery(OaJbdDocument.class).eq(OaJbdDocument::getDocNo, docNo));
+                break;
+        }
+        oaDocumentMapper.delete(Wrappers.lambdaQuery(OaDocument.class).eq(OaDocument::getDocNo, docNo));
+    }
+
+    // 新增单据
+    @Override
+    public void addDoc(JSONObject oaDocument) {
+        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(OaFormDefinition::getFieldInfo).eq(OaFormDefinition::getId, oaDocument.get("formId"));
+        OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectOne(queryWrapper);
+        String sign = oaFormDefinition.getFieldInfo();
+
+        switch (sign) {
+            case "QJD":
+                oaQjdDocumentService.addQjDocument(JSON.parseObject(oaDocument.toJSONString(), OaQjdDocument.class));
+                break;
+            case "JBD":
+                oaJbdDocumentService.add(JSON.parseObject(oaDocument.toJSONString(), OaJbdDocument.class));
+                break;
+        }
+    }
+
+    // 更新单据
+    @Override
+    public void updateDoc(JSONObject jsonDocument) {
+        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(OaFormDefinition::getFieldInfo).eq(OaFormDefinition::getId, jsonDocument.get("formId"));
+        OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectOne(queryWrapper);
+        String sign = oaFormDefinition.getFieldInfo();
+
+        switch (sign) {
+            case "QJD":
+                oaQjdDocumentService.updateQjDocument(JSON.parseObject(jsonDocument.toJSONString(), OaQjdDocument.class));
+                break;
+            case "JBD":
+                oaJbdDocumentService.update(JSON.parseObject(jsonDocument.toJSONString(), OaJbdDocument.class));
+                break;
+        }
+    }
+
+    // 提交单据
+    @Transactional
+    @Override
+    public void submit(String docNo, Integer docStatus) {
+        if (docStatus != 1) {
+            throw new RuntimeException("单据提交异常,请联系管理员!");
+        } else {
+            LambdaQueryWrapper<OaDocument> queryWrapper = Wrappers.lambdaQuery();
+            queryWrapper.eq(OaDocument::getDocNo, docNo);
+            OaDocument oaDocument = oaDocumentMapper.selectOne(queryWrapper);
+            if (oaDocument.getDocStatus() == 1) {
+                throw new RuntimeException("单据已提交,请勿重复提交!");
+            }
+        }
+
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        Integer tenantId = SecurityUtils.getTenantId();
+        String username = SecurityUtils.getUsername();
+        LocalDateTime now = LocalDateTime.now();
+
+        String formSign = getFormSign(docNo);
+
+        switch (formSign) {
+            case "QJD":
+                oaQjdDocumentMapper.update(null, Wrappers.lambdaUpdate(OaQjdDocument.class)
+                        .set(OaQjdDocument::getDocStatus, docStatus)
+                        .set(OaQjdDocument::getUpdateBy, username)
+                        .set(OaQjdDocument::getUpdateTime, now)
+                        .eq(OaQjdDocument::getDocNo, docNo));
+                break;
+            case "JBD":
+                oaJbdDocumentMapper.update(null, Wrappers.lambdaUpdate(OaJbdDocument.class)
+                        .set(OaJbdDocument::getDocStatus, docStatus)
+                        .set(OaJbdDocument::getUpdateBy, username)
+                        .set(OaJbdDocument::getUpdateTime, now)
+                        .eq(OaJbdDocument::getDocNo, docNo));
+                break;
+        }
+        oaDocumentMapper.update(null, Wrappers.lambdaUpdate(OaDocument.class)
+                .set(OaDocument::getDocStatus, docStatus)
+                .set(OaDocument::getUpdateBy, username)
+                .set(OaDocument::getUpdateTime, now)
+                .eq(OaDocument::getDocNo, docNo));
+
+        // 生成两条审批记录数据
+        OaApproval oaApproval = new OaApproval();
+        oaApproval.setDocNo(docNo);
+        oaApproval.setType(0);
+        oaApproval.setApprovalStatus(1);
+        oaApproval.setApprovalUid(226L);
+        oaApproval.setCreateBy(username);
+        oaApproval.setCreateTime(now);
+        oaApproval.setSubmitDate(now);
+        oaApproval.setDeptId(deptId);
+        oaApproval.setTenantId(tenantId);
+        oaApprovalMapper.insert(oaApproval);
+
+        OaApproval oaApproval1 = new OaApproval();
+        oaApproval1.setDocNo(docNo);
+        oaApproval1.setType(1);
+        oaApproval1.setApprovalStatus(1);
+        oaApproval1.setApprovalUid(157L);
+        oaApproval1.setCreateBy(username);
+        oaApproval1.setCreateTime(now);
+        oaApproval1.setSubmitDate(now);
+        oaApproval1.setDeptId(deptId);
+        oaApproval1.setTenantId(tenantId);
+        oaApprovalMapper.insert(oaApproval1);
+
+    }
+
+    // 获取单据类型
+    private String getFormSign(String docNo) {
+        if (StringUtils.isBlank(docNo)) {
+            throw new RuntimeException("单据号不能为空!");
+        } else if (docNo.split("-").length != 2 ||
+                docNo.split("-")[0].length() > 4 ||
+                docNo.split("-")[0].length() < 3 ||
+                docNo.split("-")[1].length() != 12) {
+            throw new RuntimeException("单据号格式错误!");
+        }
+        return docNo.split("-")[0];
+    }
+
+}

+ 331 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaFormDefinitionServiceImpl.java

@@ -0,0 +1,331 @@
+package com.usky.oa.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.datascope.context.DataScopeContextHolder;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.domain.OaFormDefinition;
+import com.usky.oa.mapper.OaDocumentMapper;
+import com.usky.oa.mapper.OaFormDefinitionMapper;
+import com.usky.oa.service.OaDocumentService;
+import com.usky.oa.service.OaFormDefinitionService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.oa.service.vo.OaFormNameResponseVO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 表单定义表 服务实现类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Service
+public class OaFormDefinitionServiceImpl extends AbstractCrudService<OaFormDefinitionMapper, OaFormDefinition> implements OaFormDefinitionService {
+
+    @Autowired
+    private OaFormDefinitionMapper oaFormDefinitionMapper;
+
+    @Autowired
+    private OaDocumentMapper oaDocumentMapper;
+
+    /**
+     * 新增/更新 表单
+     * 此方法负责验证表单定义的合法性,包括表单名称和标识的唯一性、长度限制,并最终保存合法的表单定义
+     * @param oaFormDefinition 表单定义对象,包含表单的详细信息
+     * @throws BusinessException 当表单名称或标识不符合规范或已存在时抛出
+     */
+    @Override
+    public void addForm(OaFormDefinition oaFormDefinition) {
+
+        String formName = oaFormDefinition.getFormName();
+        String formSign = oaFormDefinition.getFormSign();
+        String formExplain = oaFormDefinition.getFormExplain();
+        // 判断 表单名称、标识、说明 是否为空或超长
+        validateFormProperties(formName, formSign, formExplain);
+
+        // 判断 表单分组 是否为空、有效
+        isValidFormGroup(oaFormDefinition.getFormGroup());
+
+        if (Objects.isNull(oaFormDefinition.getFormType())) {
+            throw new BusinessException("表单字段信息不能为空");
+        } else if (oaFormDefinition.getFormType() < 0 || oaFormDefinition.getFormType() > 1) {
+            throw new BusinessException("表单类型不正确");
+        }
+
+        // 判断 表单可见范围 是否为空、有效
+        validFromScope(oaFormDefinition);
+
+        // 获取用户基本信息
+        Long userId = SecurityUtils.getUserId();
+        Integer tenantId = SecurityUtils.getTenantId();
+        String username = SecurityUtils.getUsername();
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        LocalDateTime now = LocalDateTime.now();
+
+        // 判断表单是新增或者修改
+        if (oaFormDefinition.getId() == null) {
+            // BeanUtils.copyBeanProp(oaFormDefinition, oaFormDefinition);
+            // 判断表单名称和标识是否重复
+            selectByNameOrSign(formName, formSign);
+
+            oaFormDefinition.setCreateBy(username);
+            oaFormDefinition.setDeptId(deptId);
+            oaFormDefinition.setTenantId(tenantId);
+            oaFormDefinition.setCreateTime(now);
+            oaFormDefinition.setFormVersion(1);
+            oaFormDefinition.setFormStatus(2);
+            oaFormDefinitionMapper.insert(oaFormDefinition);
+        } else {
+            oaFormDefinition.setUpdateBy(username);
+            oaFormDefinition.setUpdateTime(now);
+
+            OaFormDefinition oaFormDefinition1 = oaFormDefinitionMapper.selectById(oaFormDefinition.getId());
+            // 判断表单版本号是否需要更新
+            if (versionUpdateValid(oaFormDefinition)) {
+                oaFormDefinition.setFormVersion(oaFormDefinition1.getFormVersion() + 1);
+            }
+            if (!Objects.equals(oaFormDefinition.getFormSign(), oaFormDefinition1.getFormSign())) {
+                throw new BusinessException("表单标识不可修改!");
+            }
+
+            oaFormDefinitionMapper.updateById(oaFormDefinition);
+        }
+    }
+
+    /**
+     * 删除表单
+     * @param formId 表单ID,用于删除特定的表单定义
+     */
+    @Override
+    public void delForm(Integer formId) {
+        if (formId > 0) {
+            OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectById(formId);
+            if (oaFormDefinition == null) {
+                throw new BusinessException("表单不存在!");
+            }
+            if (validDelete(formId) != null) {
+                throw new BusinessException("当前表单下存在单据,不可删除!");
+            }
+            oaFormDefinitionMapper.deleteById(oaFormDefinition);
+        } else {
+            throw new BusinessException("表单ID不能为空或者小于0");
+        }
+    }
+
+    // 判断表单下是否存在已生成单据
+    private OaDocument validDelete(Integer formId) {
+        LambdaQueryWrapper<OaDocument> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaDocument::getFormId, formId);
+        return oaDocumentMapper.selectOne(queryWrapper);
+    }
+
+
+    // 表单管理-分页查询
+    @Override
+    public CommonPage<OaFormDefinition> pageList(Integer formId, String formName, Integer formGroup, Integer formStatus, Integer pageNum, Integer pageSize) {
+        IPage<OaFormDefinition> page = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(formId != null, OaFormDefinition::getId, formId)
+                .like(StringUtils.isNotBlank(formName), OaFormDefinition::getFormName, formName)
+                .eq(formGroup != null, OaFormDefinition::getFormGroup, formGroup)
+                .eq(formStatus != null, OaFormDefinition::getFormStatus, formStatus)
+                .orderByDesc(OaFormDefinition::getId)
+                // 数据权限控制
+                .apply(Objects.nonNull(DataScopeContextHolder.getDataScopeSql()), DataScopeContextHolder.getDataScopeSql());
+        return ToCommonPage(oaFormDefinitionMapper.selectPage(page, queryWrapper));
+    }
+
+    // 表单管理-修改表单状态
+    @Override
+    public void validUpdateStatus(Integer formId, Integer formStatus) {
+        if (formId == null || formId <= 0) {
+            throw new BusinessException("表单ID不能为空或者小于0!");
+        }
+        OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectById(formId);
+        if (oaFormDefinition == null) {
+            throw new BusinessException("表单不存在!");
+        }
+
+        if (formStatus == null || formStatus < 1 || formStatus > 2) {
+            throw new BusinessException("表单状态为空或不在设定值范围!");
+        }
+        oaFormDefinition.setFormStatus(formStatus);
+        oaFormDefinitionMapper.updateById(oaFormDefinition);
+    }
+
+    // 我的申请-根据权限查询表单
+    @Override
+    public List<OaFormDefinition> selectByScope(String formSign) {
+        Long userId = SecurityUtils.getUserId();
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        Integer tenantId = SecurityUtils.getTenantId();
+
+        List<OaFormDefinition> oaFormDefinitions = new ArrayList<>();
+
+        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaFormDefinition::getTenantId, tenantId);
+
+        if (StringUtils.isNotBlank(formSign)) {
+            queryWrapper.eq(OaFormDefinition::getFormSign, formSign);
+            OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectOne(queryWrapper);
+            if (oaFormDefinition != null) {
+                oaFormDefinitions.add(oaFormDefinition);
+            }
+            return oaFormDefinitions;
+        }
+
+        queryWrapper.eq(OaFormDefinition::getFormStatus, 1)
+                .and(qw -> qw
+                        .eq(OaFormDefinition::getFormScope, 1)
+                        .or()
+                        .apply("FIND_IN_SET('" + deptId + "', dept_ids) > 0")
+                        .or()
+                        .apply("FIND_IN_SET('" + userId + "', user_ids) > 0"));
+        oaFormDefinitions = oaFormDefinitionMapper.selectList(queryWrapper);
+        return oaFormDefinitions;
+    }
+
+    // 表单管理-根据权限查询表单
+    @Override
+    public List<OaFormNameResponseVO> getFormName(String formSign, String formName, Integer formId) {
+        Long userId = SecurityUtils.getUserId();
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        Integer tenantId = SecurityUtils.getTenantId();
+        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(OaFormDefinition::getId, OaFormDefinition::getFormName, OaFormDefinition::getFormSign)
+                .eq(OaFormDefinition::getTenantId, tenantId)
+                .eq(StringUtils.isNotBlank(formSign), OaFormDefinition::getFormSign, formSign)
+                .eq(StringUtils.isNotBlank(formName), OaFormDefinition::getFormName, formName)
+                .eq(formId != null && formId > 0, OaFormDefinition::getId, formId)
+                .eq(OaFormDefinition::getFormStatus, 1)
+                .and(qw -> qw
+                        .eq(OaFormDefinition::getFormScope, 1)
+                        .or()
+                        .apply("FIND_IN_SET('" + deptId + "', dept_ids) > 0")
+                        .or()
+                        .apply("FIND_IN_SET('" + userId + "', user_ids) > 0"));
+        List<OaFormDefinition> oaFormDefinitions = oaFormDefinitionMapper.selectList(queryWrapper);
+
+        List<OaFormNameResponseVO> formNameList = new ArrayList<>();
+        for (OaFormDefinition oaFormDefinition : oaFormDefinitions) {
+            OaFormNameResponseVO oaFormNameResponseVO = new OaFormNameResponseVO();
+            oaFormNameResponseVO.setFormId(oaFormDefinition.getId());
+            oaFormNameResponseVO.setFormName(oaFormDefinition.getFormName());
+            oaFormNameResponseVO.setFormSign(oaFormDefinition.getFormSign());
+            formNameList.add(oaFormNameResponseVO);
+        }
+        return formNameList;
+    }
+
+
+    // 表单版本更新验证
+    private Boolean versionUpdateValid(OaFormDefinition oaFormDefinition) {
+        boolean update = false;
+        OaFormDefinition selectOne = oaFormDefinitionMapper.selectById(oaFormDefinition.getId());
+        if (!selectOne.getFlowInfo().equals(oaFormDefinition.getFlowInfo()) || !selectOne.getFormExplain().equals(oaFormDefinition.getFormExplain())) {
+            update = true;
+        }
+        return update;
+    }
+
+    /**
+     * 根据表单id、名称查询
+     * @param formName 表单名称,用于查询特定的表单定义
+     * @return 返回查询到的表单定义对象,如果没有找到匹配的表单,则返回null
+     */
+    public void selectByNameOrSign(String formName, String formSign) {
+        LambdaQueryWrapper<OaFormDefinition> queryName = Wrappers.lambdaQuery();
+        queryName.eq(StringUtils.isNotBlank(formName), OaFormDefinition::getFormName, formName);
+        OaFormDefinition fromByName = oaFormDefinitionMapper.selectOne(queryName);
+
+        LambdaQueryWrapper<OaFormDefinition> querySign = Wrappers.lambdaQuery();
+        querySign.eq(StringUtils.isNotBlank(formSign), OaFormDefinition::getFormSign, formSign);
+        OaFormDefinition fromBySign = oaFormDefinitionMapper.selectOne(querySign);
+
+        if (fromByName != null) {
+            throw new BusinessException("表单名称已存在,请更换");
+        } else if (fromBySign != null) {
+            throw new BusinessException("表单标识已存在,请更换");
+        }
+    }
+
+    // 表单管理-表单属性(表单名称、标识、说明)验证
+    private void validateFormProperties(String formName, String formSign, String formExplain) {
+        // 判断表单名称是否为空或者超长
+        if (StringUtils.isBlank(formName) || formName.length() > 10) {
+            throw new BusinessException("表单名称不能为空或空字符串");
+        }
+
+        // 判断表单标识是否为空或者超长
+        if (StringUtils.isBlank(formSign)) {
+            throw new BusinessException("表单标识不能为空");
+        } else if (formSign.length() < 3 || formSign.length() > 4) {
+            throw new BusinessException("表单标识长度不能少于3个字符或超过4个字符");
+        } else if (!formSign.matches("^[A-Z]+$")) {
+            throw new BusinessException("表单标识只能包含大写字母!");
+        }
+
+        // 判断表单说明是否超长
+        if (StringUtils.isNotBlank(formExplain) && formExplain.length() > 100) {
+            throw new BusinessException("表单说明长度不能超过100个字符");
+        }
+    }
+
+    // 判断表单所在分组是否有效
+    private void isValidFormGroup(Integer formGroup) {
+        if (formGroup == null) {
+            throw new BusinessException("表单所在分组不能为空");
+        } else if (formGroup < 0 || formGroup > 6) {
+            throw new BusinessException("表单所在分组异常!请联系管理员");
+        }
+    }
+
+    // 校验表单可见范围是否有效
+    private void validFromScope(OaFormDefinition oaFormDefinition) {
+        if (oaFormDefinition.getFormScope() == null) {
+            throw new BusinessException("表单可见范围不能为空");
+        } else {
+            Integer formScope = oaFormDefinition.getFormScope();
+            String deptIds = oaFormDefinition.getDeptIds();
+            String userIds = oaFormDefinition.getUserIds();
+            switch (formScope) {
+                case 0:
+                    if (StringUtils.isBlank(deptIds)) {
+                        throw new BusinessException("表单可见范围为部门,部门集合不能为空");
+                    } else if (!deptIds.matches("^(?:\\d+)(,\\d+)*$")) {
+                        throw new BusinessException("部门集合格式不正确!");
+                    }
+                    break;
+
+                case 1:
+                    break;
+
+                case 2:
+                    if (StringUtils.isBlank(userIds)) {
+                        throw new BusinessException("表单可见范围为人员,人员集合不能为空");
+                    } else if (!userIds.matches("^(?:\\d+)(,\\d+)*$")) {
+                        throw new BusinessException("人员集合格式不正确!");
+                    }
+                    break;
+                default:
+                    throw new BusinessException("表单可见范围为异常!请联系管理员");
+            }
+        }
+
+    }
+
+}

+ 188 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaJbdDocumentServiceImpl.java

@@ -0,0 +1,188 @@
+package com.usky.oa.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.oa.domain.OaApproval;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.domain.OaJbdDocument;
+import com.usky.oa.mapper.OaApprovalMapper;
+import com.usky.oa.mapper.OaDocumentMapper;
+import com.usky.oa.mapper.OaJbdDocumentMapper;
+import com.usky.oa.service.OaJbdDocumentService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.oa.service.enums.OaBuiltInDocument;
+import org.apache.commons.lang3.RandomUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+
+/**
+ * <p>
+ * 加班单据表 服务实现类
+ * </p>
+ *
+ * @author fu
+ * @since 2025-01-02
+ */
+@Service
+public class OaJbdDocumentServiceImpl extends AbstractCrudService<OaJbdDocumentMapper, OaJbdDocument> implements OaJbdDocumentService {
+
+    @Autowired
+    private OaJbdDocumentMapper oaJbdDocumentMapper;
+
+    @Autowired
+    private OaDocumentMapper oaDocumentMapper;
+
+    @Autowired
+    private OaApprovalMapper oaApprovalMapper;
+
+    @Override
+    public void add(OaJbdDocument oaJbdDocument) {
+        Long userId = SecurityUtils.getUserId();
+        String username = SecurityUtils.getUsername();
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        Integer tenantId = SecurityUtils.getTenantId();
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+        LocalDateTime now = LocalDateTime.now();
+        String formattedDate = now.format(formatter);
+        String sign = OaBuiltInDocument.JBD.getSign();
+        String docNo = sign + "-" + formattedDate;
+
+        validateOaJbDocument(oaJbdDocument);
+
+        oaJbdDocument.setDocNo(docNo);
+        oaJbdDocument.setAccountingMethod(0);
+        oaJbdDocument.setProposer(userId);
+        oaJbdDocument.setCreateBy(username);
+        oaJbdDocument.setCreateTime(now);
+        oaJbdDocument.setDeptId(deptId);
+        oaJbdDocument.setTenantId(tenantId);
+        oaJbdDocumentMapper.insert(oaJbdDocument);
+
+        OaDocument oaDocument = new OaDocument();
+        oaDocument.setFormId(oaJbdDocument.getFormId());
+        oaDocument.setType(sign);
+        oaDocument.setDocNo(docNo);
+        oaDocument.setProposer(userId);
+        oaDocument.setDocStatus(oaJbdDocument.getDocStatus());
+        oaDocument.setCreateBy(username);
+        oaDocument.setCreateTime(oaJbdDocument.getCreateTime());
+        oaDocument.setDeptId(deptId);
+        oaDocument.setTenantId(tenantId);
+        oaDocumentMapper.insert(oaDocument);
+
+        // 如果直接提交则生成一条单据记录
+        Integer docStatus = oaJbdDocument.getDocStatus();
+        if (docStatus.equals(1)) {
+            // 生成一条审批记录数据
+            OaApproval oaApproval = new OaApproval();
+            oaApproval.setDocNo(oaJbdDocument.getDocNo());
+            oaApproval.setType(0);
+            oaApproval.setApprovalStatus(1);
+            long approvalUid = RandomUtils.nextBoolean() ? 226L : 157L;
+            oaApproval.setApprovalUid(approvalUid);
+            oaApproval.setCreateBy(oaJbdDocument.getCreateBy());
+            oaApproval.setCreateTime(now);
+            oaApproval.setSubmitDate(now);
+            oaApproval.setDeptId(oaJbdDocument.getDeptId());
+            oaApproval.setTenantId(oaJbdDocument.getTenantId());
+            oaApprovalMapper.insert(oaApproval);
+        }
+    }
+
+    @Override
+    public void update(OaJbdDocument oaJbdDocument) {
+        if (StringUtils.isBlank(oaJbdDocument.getDocNo())) {
+            throw new BusinessException("更新单据编号传参异常!");
+        }
+        validateOaJbDocument(oaJbdDocument);
+        oaJbdDocument.setUpdateBy(SecurityUtils.getUsername());
+        oaJbdDocument.setUpdateTime(LocalDateTime.now());
+        oaJbdDocumentMapper.updateById(oaJbdDocument);
+
+        oaDocumentMapper.update(null, Wrappers.lambdaUpdate(OaDocument.class)
+                .set(OaDocument::getDocStatus, oaJbdDocument.getDocStatus())
+                .set(OaDocument::getUpdateBy, oaJbdDocument.getCreateBy())
+                .set(OaDocument::getUpdateTime, oaJbdDocument.getUpdateTime())
+        );
+    }
+
+    /**
+     * @description: 验证加班单据参数
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 18:29
+     * @param: [oaJbdDocument]
+     * @return: void
+     **/
+    private void validateOaJbDocument(OaJbdDocument oaJbdDocument) {
+
+        if (oaJbdDocument.getFormId() == null || oaJbdDocument.getFormId() <= 0) {
+            throw new BusinessException("表单ID必须大于0!");
+        }
+
+        LocalDateTime startTime = oaJbdDocument.getStartTime();
+        LocalDateTime endTime = oaJbdDocument.getEndTime();
+        Integer duration = oaJbdDocument.getDuration();
+
+        if (startTime == null || endTime == null || startTime.isAfter(endTime)) {
+            throw new BusinessException("加班开始时间或结束时间输入异常!请确保开始时间不晚于结束时间");
+        }
+
+        if (oaJbdDocument.getDuration() == null || oaJbdDocument.getDuration() <= 0) {
+            throw new BusinessException("加班时长必须大于0!");
+        }
+
+        long hours = ChronoUnit.HOURS.between(startTime, endTime);
+        long days = ChronoUnit.DAYS.between(startTime, endTime);
+        if (days > 0) {
+            hours -= days * 16;
+        }
+        if (hours != duration) {
+            throw new BusinessException("加班时长与实际时长不一致,请重试!");
+        }
+
+        if (StringUtils.isBlank(oaJbdDocument.getReason())) {
+            throw new BusinessException("加班原因不能为空!");
+        } else if (oaJbdDocument.getReason().length() > 255) {
+            throw new BusinessException("加班原因超出字数限制,请重试!");
+        }
+
+        if (oaJbdDocument.getImage() == null) {
+            throw new BusinessException("打卡记录及日报图片不能为空!");
+        } else if (oaJbdDocument.getImage().length() > 500) {
+            throw new BusinessException("上传图片数量超出限制,请重试!");
+        }
+    }
+
+    @Override
+    public void delByDocNo(String docNo) {
+
+        if (StringUtils.isBlank(docNo)) {
+            throw new BusinessException("加班单据编号不能为空!");
+        }
+
+        Integer tenantId = SecurityUtils.getTenantId();
+        Long userId = SecurityUtils.getUserId();
+
+        LambdaQueryWrapper<OaJbdDocument> jbdDeleteWrapper = new LambdaQueryWrapper<>();
+        jbdDeleteWrapper.eq(OaJbdDocument::getTenantId, tenantId)
+                .eq(OaJbdDocument::getProposer, userId)
+                .eq(OaJbdDocument::getDocNo, docNo);
+        oaJbdDocumentMapper.delete(jbdDeleteWrapper);
+
+        LambdaQueryWrapper<OaDocument> deleteWrapper = new LambdaQueryWrapper<>();
+        deleteWrapper.eq(OaDocument::getTenantId, tenantId)
+                .eq(OaDocument::getProposer, userId)
+                .eq(OaDocument::getDocNo, docNo);
+        oaDocumentMapper.delete(deleteWrapper);
+    }
+
+}

+ 217 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/impl/OaQjdDocumentServiceImpl.java

@@ -0,0 +1,217 @@
+package com.usky.oa.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.log.annotation.Log;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.oa.domain.OaApproval;
+import com.usky.oa.domain.OaDocument;
+import com.usky.oa.domain.OaFormDefinition;
+import com.usky.oa.domain.OaQjdDocument;
+import com.usky.oa.mapper.OaApprovalMapper;
+import com.usky.oa.mapper.OaDocumentMapper;
+import com.usky.oa.mapper.OaFormDefinitionMapper;
+import com.usky.oa.mapper.OaQjdDocumentMapper;
+import com.usky.oa.service.OaQjdDocumentService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.oa.service.enums.OaBuiltInDocument;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.RandomUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * <p>
+ * 请假单据表 服务实现类
+ * </p>
+ *
+ * @author fu
+ * @since 2024-12-10
+ */
+@Slf4j
+@Service
+public class OaQjdDocumentServiceImpl extends AbstractCrudService<OaQjdDocumentMapper, OaQjdDocument> implements OaQjdDocumentService {
+
+    @Autowired
+    private OaQjdDocumentMapper oaQjdDocumentMapper;
+
+    @Autowired
+    private OaFormDefinitionMapper oaFormDefinitionMapper;
+
+    @Autowired
+    private OaDocumentMapper oaDocumentMapper;
+
+    @Autowired
+    private OaApprovalMapper oaApprovalMapper;
+
+    @Override
+    public void addQjDocument(OaQjdDocument oaQjdDocument) {
+
+        // 校验表单数据
+        validateOaQjDocument(oaQjdDocument);
+
+        Long userId = SecurityUtils.getUserId();
+        String username = SecurityUtils.getUsername();
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        Integer tenantId = SecurityUtils.getTenantId();
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+        LocalDateTime now = LocalDateTime.now();
+        String formattedDate = now.format(formatter);
+
+        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(OaFormDefinition::getFormSign).eq(OaFormDefinition::getId, oaQjdDocument.getFormId());
+        OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectOne(queryWrapper);
+        String sign = oaFormDefinition.getFormSign();
+        String docNo = sign + "-" + formattedDate;
+
+        // 插入请假表数据
+        oaQjdDocument.setDocNo(docNo);
+        oaQjdDocument.setProposer(userId);
+        oaQjdDocument.setCreateBy(username);
+        oaQjdDocument.setCreateTime(now);
+        oaQjdDocument.setDeptId(deptId);
+        oaQjdDocument.setTenantId(tenantId);
+        oaQjdDocumentMapper.insert(oaQjdDocument);
+
+        // 插入单据表数据
+        OaDocument oaDocument = new OaDocument();
+        oaDocument.setFormId(oaQjdDocument.getFormId());
+        oaDocument.setType(sign);
+        oaDocument.setDocNo(docNo);
+        oaDocument.setProposer(userId);
+        oaDocument.setDocStatus(oaQjdDocument.getDocStatus());
+        oaDocument.setCreateBy(username);
+        oaDocument.setCreateTime(oaQjdDocument.getCreateTime());
+        oaDocument.setDeptId(deptId);
+        oaDocument.setTenantId(tenantId);
+        oaDocumentMapper.insert(oaDocument);
+
+        if (oaQjdDocument.getDocStatus().equals(1)) {
+            // 生成一条审批记录数据
+            OaApproval oaApproval = new OaApproval();
+            oaApproval.setDocNo(docNo);
+            oaApproval.setType(0);
+            oaApproval.setApprovalStatus(1);
+            // 随机选择一个审批人
+            long approvalUid = RandomUtils.nextBoolean() ? 226L : 157L;
+            oaApproval.setApprovalUid(approvalUid);
+            oaApproval.setCreateBy(username);
+            oaApproval.setCreateTime(now);
+            oaApproval.setSubmitDate(now);
+            oaApproval.setDeptId(deptId);
+            oaApproval.setTenantId(tenantId);
+            oaApprovalMapper.insert(oaApproval);
+        }
+    }
+
+    @Override
+    public void updateQjDocument(OaQjdDocument oaQjdDocument) {
+
+        if (StringUtils.isBlank(oaQjdDocument.getDocNo())) {
+            throw new BusinessException("更新请假单据ID异常");
+        }
+
+        validateOaQjDocument(oaQjdDocument);
+        String username = SecurityUtils.getUsername();
+        LocalDateTime now = LocalDateTime.now();
+        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        Integer tenantId = SecurityUtils.getTenantId();
+
+        oaQjdDocument.setUpdateBy(username);
+        oaQjdDocument.setUpdateTime(now);
+        oaQjdDocumentMapper.updateById(oaQjdDocument);
+
+        oaDocumentMapper.update(null, Wrappers.lambdaUpdate(OaDocument.class)
+                .set(OaDocument::getDocStatus, oaQjdDocument.getDocStatus())
+                .set(OaDocument::getUpdateBy, username)
+                .set(OaDocument::getUpdateTime, oaQjdDocument.getUpdateTime())
+        );
+
+        if (oaQjdDocument.getDocStatus().equals(1)) {
+            // 生成一条审批记录数据
+            OaApproval oaApproval = new OaApproval();
+            oaApproval.setDocNo(oaQjdDocument.getDocNo());
+            oaApproval.setType(0);
+            oaApproval.setApprovalStatus(1);
+            // 随机选择一个审批人
+            long approvalUid = RandomUtils.nextBoolean() ? 226L : 157L;
+            oaApproval.setApprovalUid(approvalUid);
+            oaApproval.setCreateBy(username);
+            oaApproval.setCreateTime(now);
+            oaApproval.setSubmitDate(now);
+            oaApproval.setDeptId(deptId);
+            oaApproval.setTenantId(tenantId);
+            oaApprovalMapper.insert(oaApproval);
+        }
+    }
+
+    /**
+     * @description: 校验请假单据表数据
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2024/12/27 10:04
+     * @param: [oaQjDocument]
+     * @return: void
+     **/
+    public void validateOaQjDocument(OaQjdDocument oaQjdDocument) {
+
+        if (oaQjdDocument.getFormId() == null || oaQjdDocument.getFormId() <= 0) {
+            throw new BusinessException("表单ID不能为空或小于等于0");
+        }
+
+        if (StringUtils.isBlank(oaQjdDocument.getType())) {
+            throw new BusinessException("请假类型不能为空");
+        }
+
+        if (oaQjdDocument.getType().length() > 4) {
+            throw new BusinessException("请假类型长度不能超过4个字符");
+        }
+
+        if (oaQjdDocument.getStartTime() == null || oaQjdDocument.getEndTime() == null) {
+            throw new BusinessException("请假开始时间或结束时间不能为空");
+        }
+
+        if (oaQjdDocument.getStartTime().isAfter(oaQjdDocument.getEndTime())) {
+            throw new BusinessException("请假开始时间不能大于结束时间");
+        }
+
+        if (oaQjdDocument.getDuration() == null || oaQjdDocument.getDuration() <= 0) {
+            throw new BusinessException("请假时长不能为空或小于等于0");
+        }
+
+        if (StringUtils.isBlank(oaQjdDocument.getReason())) {
+            throw new BusinessException("请假原因不能为空");
+        }
+
+        if (oaQjdDocument.getReason().length() > 255) {
+            throw new BusinessException("请假原因超出字数限制,请重试");
+        }
+
+        if (oaQjdDocument.getImage() != null && oaQjdDocument.getImage().length() > 500) {
+            throw new BusinessException("上传图片数量超出限制,请重试");
+        }
+    }
+
+    @Override
+    public void delQjDocument(String docNo) {
+
+        if (StringUtils.isBlank(docNo)) {
+            throw new BusinessException("请假单据编号不能为空!");
+        }
+
+        LambdaQueryWrapper<OaQjdDocument> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(OaQjdDocument::getDocNo, docNo);
+        oaQjdDocumentMapper.delete(queryWrapper);
+
+        LambdaQueryWrapper<OaDocument> deleteWrapper = Wrappers.lambdaQuery();
+        deleteWrapper.eq(OaDocument::getDocNo, docNo);
+        oaDocumentMapper.delete(deleteWrapper);
+    }
+}

+ 33 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/utils/OaDefinitionDocumentInfo.java

@@ -0,0 +1,33 @@
+package com.usky.oa.service.utils;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2024/12/25
+ */
+public class OaDefinitionDocumentInfo {
+    private String sign;
+    private String name;
+
+    public OaDefinitionDocumentInfo(String sign, String name) {
+        this.sign = sign;
+        this.name = name;
+    }
+
+    public String getSign() {
+        return sign;
+    }
+
+    public void setSign(String sign) {
+        this.sign = sign;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 72 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/utils/OaSendMessageCenter.java

@@ -0,0 +1,72 @@
+package com.usky.oa.service.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.system.domain.SysUser;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/1/9
+ */
+@Slf4j
+@Configuration
+public class OaSendMessageCenter {
+
+    private static final String INFO_TITLE = "审批提醒";
+    private static final String INFO_CONTENT = "的申请";
+    private static final int INFO_TYPE = 6;
+
+    /*public void sendAsyncMessage(PmWorkReport newReport) {
+        String username = newReport.getCreateBy();
+        Long submitterId = newReport.getSubmitterId();
+        log.info(username + "的申请开始发送消息中心-----------------------------------");
+        List<Long> userId = new ArrayList<>();
+        if (!newReport.getCcTo().isEmpty()) {
+            userId = Optional.of(newReport.getCcTo())
+                    .map(ccTo -> Arrays.stream(ccTo.split(","))
+                            .map(Long::parseLong)
+                            .collect(Collectors.toList()))
+                    .orElse(Collections.emptyList());
+        } else {
+            throw new BusinessException( newReport.getCreateBy() + "的报告:" + newReport.getId() + ",抄送人为空,无需发送消息中心");
+        }
+        LambdaQueryWrapper<SysUser> nickNameQuery = Wrappers.lambdaQuery();
+        nickNameQuery.select(SysUser::getNickName)
+                .eq(SysUser::getUserId, submitterId);
+        SysUser nickName = sysUserMapper.selectOne(nickNameQuery);
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("infoTitle", INFO_TITLE);
+        jsonObject.put("infoContent", nickName.getNickName() + INFO_CONTENT);
+        jsonObject.put("infoType", INFO_TYPE);
+        jsonObject.put("id", newReport.getId());
+        jsonObject.put("infoTypeName", INFO_TITLE);
+        jsonObject.put("userName", newReport.getCreateBy());
+        if (!userId.isEmpty()) {
+            jsonObject.put("userIds", userId);
+        }
+        try {
+            // 推送消息中心
+            ApiResult<Void> voidApiResult = remoteMceService.addMce(jsonObject.toString());
+
+            if (voidApiResult.isSuccess()) {
+                log.info("报告消息发送成功!");
+            } else {
+                log.error("报告消息发送失败!");
+            }
+        } catch (Exception e) {
+            log.error("报告发送消息时发生异常", e);
+        }
+        log.info(username + "的工作报告发送消息中心完成-----------------------------------");
+    }*/
+
+}

+ 54 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/vo/OaApprovalCountVO.java

@@ -0,0 +1,54 @@
+package com.usky.oa.service.vo;
+
+import lombok.Data;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2024/12/30
+ */
+@Data
+public class OaApprovalCountVO {
+
+    /**
+     * @description: 待处理
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 9:54
+     * @param:
+     * @return:
+     **/
+    private Integer pendingSum;
+
+    /**
+     * @description: 已处理
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 9:54
+     * @param:
+     * @return:
+     **/
+    private Integer alreadySum;
+
+    /**
+     * @description: 已发起
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 9:54
+     * @param:
+     * @return:
+     **/
+    private Integer myInitiated;
+
+    /**
+     * @description: 我收到的
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/1/2 9:54
+     * @param:
+     * @return:
+     **/
+    private Integer myReceived;
+
+}

+ 23 - 0
service-oa/service-oa-biz/src/main/java/com/usky/oa/service/vo/OaFormNameResponseVO.java

@@ -0,0 +1,23 @@
+package com.usky.oa.service.vo;
+
+import lombok.Data;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/1/3
+ */
+@Data
+public class OaFormNameResponseVO {
+
+    /** 表单id */
+    private Integer formId;
+
+    /** 表单标识 */
+    private String formSign;
+
+    /** 表单名 */
+    private String formName;
+
+}

+ 1 - 1
service-oa/service-oa-biz/src/main/resources/bootstrap.yml

@@ -1,6 +1,6 @@
 # Tomcat
 server:
-  port: 9889
+  port: 8100
 
 # Spring
 spring: 

+ 23 - 0
service-oa/service-oa-biz/src/main/resources/mapper/oa/OaApprovalMapper.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.oa.mapper.OaApprovalMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.oa.domain.OaApproval">
+        <id column="id" property="id" />
+        <result column="doc_no" property="docNo" />
+        <result column="approval_uid" property="approvalUid" />
+        <result column="type" property="type" />
+        <result column="approval_status" property="approvalStatus" />
+        <result column="opinion" property="opinion" />
+        <result column="submit_date" property="submitDate" />
+        <result column="approval_date" property="approvalDate" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>

+ 81 - 0
service-oa/service-oa-biz/src/main/resources/mapper/oa/OaDocumentMapper.xml

@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.oa.mapper.OaDocumentMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.oa.domain.OaDocument">
+        <id column="id" property="id"/>
+        <result column="form_id" property="formId"/>
+        <result column="type" property="type"/>
+        <result column="doc_no" property="docNo"/>
+        <result column="proposer" property="proposer"/>
+        <result column="doc_status" property="docStatus"/>
+        <result column="create_by" property="createBy"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_by" property="updateBy"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="dept_id" property="deptId"/>
+        <result column="tenant_id" property="tenantId"/>
+    </resultMap>
+
+    <!-- 动态创建表-->
+    <update id="createTable">
+        create table if not exists ${tableName} (
+        <foreach collection="columns" item="column" separator=",">
+            ${column.name} ${column.type}
+        </foreach>
+        , PRIMARY KEY (${primaryKey})
+        )
+    </update>
+
+    <!-- 动态更新数据 -->
+    <update id="updateData" parameterType="map">
+        update ${(tableName)}
+        <set>
+            <if test="map != null and !map.isEmpty()">
+                <foreach collection="map" item="entry" index="key" separator=",">
+                    #{key} = #{entry.value}
+                </foreach>
+            </if>
+        </set>
+        where id = #{id}
+    </update>
+
+    <!-- 动态查询数据 -->
+    <select id="selectData" parameterType="map" resultType="map">
+        select *
+        from ${tableName}
+        <where>
+            <foreach collection="conditions" item="condition" separator="and">
+                ${condition.column} ${condition.operator} #{condition.value}
+            </foreach>
+        </where>
+        <if test="limit != null and offset != null">
+            limit #{limit} offset #{offset}
+        </if>
+    </select>
+
+    <!-- 动态插入数据 -->
+    <insert id="insertData">
+        insert into ${tableName} (
+        <foreach collection="columns" item="column" separator=",">
+            ${column}
+        </foreach>
+        ) values (
+        <foreach collection="values" item="value" separator=",">
+            #{value}
+        </foreach>
+        )
+    </insert>
+
+    <!-- 动态删除数据 -->
+    <delete id="deleteData" parameterType="map">
+        delete from ${tableName}
+        <where>
+            <foreach collection="conditions" item="condition" separator="and">
+                ${condition.column} ${condition.operator} #{condition.value}
+            </foreach>
+        </where>
+    </delete>
+
+</mapper>

+ 30 - 0
service-oa/service-oa-biz/src/main/resources/mapper/oa/OaFormDefinitionMapper.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.oa.mapper.OaFormDefinitionMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.oa.domain.OaFormDefinition">
+        <id column="id" property="id" />
+        <result column="form_name" property="formName" />
+        <result column="form_group" property="formGroup" />
+        <result column="form_explain" property="formExplain" />
+        <result column="form_type" property="formType" />
+        <result column="field_info" property="fieldInfo" />
+        <result column="flow_info" property="flowInfo" />
+        <result column="form_version" property="formVersion" />
+        <result column="form_sign" property="formSign" />
+        <result column="form_image" property="formImage" />
+        <result column="form_scope" property="formScope" />
+        <result column="form_status" property="formStatus" />
+        <!--<result column="doc_no" property="docNo" />-->
+        <result column="dept_ids" property="deptIds" />
+        <result column="user_ids" property="userIds" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>

+ 26 - 0
service-oa/service-oa-biz/src/main/resources/mapper/oa/OaJbdDocumentMapper.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.oa.mapper.OaJbdDocumentMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.oa.domain.OaJbdDocument">
+        <id column="id" property="id" />
+        <result column="form_id" property="formId" />
+        <result column="doc_no" property="docNo" />
+        <result column="proposer" property="proposer" />
+        <result column="doc_status" property="docStatus" />
+        <result column="start_time" property="startTime" />
+        <result column="end_time" property="endTime" />
+        <result column="duration" property="duration" />
+        <result column="accounting_method" property="accountingMethod" />
+        <result column="reason" property="reason" />
+        <result column="image" property="image" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>

+ 25 - 0
service-oa/service-oa-biz/src/main/resources/mapper/oa/OaQjdDocumentMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.oa.mapper.OaQjdDocumentMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.oa.domain.OaQjdDocument">
+        <id column="id" property="id" />
+        <result column="type" property="type" />
+        <result column="doc_no" property="docNo" />
+        <result column="proposer" property="proposer" />
+        <result column="doc_status" property="docStatus" />
+        <result column="start_time" property="startTime" />
+        <result column="end_time" property="endTime" />
+        <result column="duration" property="duration" />
+        <result column="reason" property="reason" />
+        <result column="image" property="image" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>