zhoulisky 11 months ago
parent
commit
e4ebd16add
22 changed files with 1076 additions and 3 deletions
  1. 39 0
      kd-service-api/kd-scientific-api/pom.xml
  2. 37 0
      kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/dto/TechnicianDTO.java
  3. 143 0
      kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/entity/TechnicianEntity.java
  4. 29 0
      kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/vo/TechnicianVO.java
  5. 1 0
      kd-service-api/pom.xml
  6. 15 0
      kd-service/kd-scientific/Dockerfile
  7. 60 0
      kd-service/kd-scientific/pom.xml
  8. 19 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/ScientificApplication.java
  9. 121 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/TechnicianController.java
  10. 168 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/TechnicianExcel.java
  11. 23 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/TechnicianImporter.java
  12. 38 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/TechnicianMapper.java
  13. 139 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/TechnicianMapper.xml
  14. 65 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/ITechnicianService.java
  15. 100 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/TechnicianServiceImpl.java
  16. 35 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/wrapper/TechnicianWrapper.java
  17. 10 0
      kd-service/kd-scientific/src/main/resources/application-dev.yml
  18. 10 0
      kd-service/kd-scientific/src/main/resources/application-prod.yml
  19. 10 0
      kd-service/kd-scientific/src/main/resources/application-test.yml
  20. 2 2
      kd-service/kd-system/src/main/java/org/sky/system/mapper/DictBizMapper.xml
  21. 1 0
      kd-service/pom.xml
  22. 11 1
      pom.xml

+ 39 - 0
kd-service-api/kd-scientific-api/pom.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>kd-service-api</artifactId>
+        <groupId>org.sky</groupId>
+        <version>${revision}</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>kd-scientific-api</artifactId>
+    <name>${project.artifactId}</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>16</source>
+                    <target>16</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.sky</groupId>
+            <artifactId>kd-core-tool</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.sky</groupId>
+            <artifactId>kd-starter-cache</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 37 - 0
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/dto/TechnicianDTO.java

@@ -0,0 +1,37 @@
+
+package org.sky.scientific.pojo.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import org.sky.core.tool.utils.DateUtil;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serial;
+import java.util.Date;
+
+/**
+ * 技术人员花名册 数据传输对象实体类
+ *
+ * @author sky
+ * @since 2025-06-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TechnicianDTO extends TechnicianEntity {
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	@Schema(description = "入职时间-开始")
+	@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
+	@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
+	private Date hireStartDate;
+
+	@Schema(description = "入职时间-结束")
+	@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
+	@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
+	private Date hireEndDate;
+
+}

+ 143 - 0
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/entity/TechnicianEntity.java

@@ -0,0 +1,143 @@
+
+package org.sky.scientific.pojo.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import io.swagger.v3.oas.annotations.media.Schema;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.EqualsAndHashCode;
+import org.sky.core.tenant.mp.TenantEntity;
+import org.sky.core.tool.utils.DateUtil;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serial;
+import java.time.LocalDate;
+import java.util.Date;
+
+/**
+ * 技术人员花名册 实体类
+ *
+ * @author Kd
+ * @since 2025-06-11
+ */
+@Data
+@TableName("kd_technician")
+@Schema(description = "Technician对象")
+@EqualsAndHashCode(callSuper = true)
+public class TechnicianEntity extends TenantEntity {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 姓名
+	 */
+	@Schema(description = "姓名")
+	private String name;
+	/**
+	 * 工号
+	 */
+	@Schema(description = "工号")
+	private String number;
+	/**
+	 * 身份证号码
+	 */
+	@Schema(description = "身份证号码")
+	private String identityCard;
+	/**
+	 * 性别,1:男,2:女
+	 */
+	@Schema(description = "性别,1:男,2:女")
+	private Integer gender;
+	/**
+	 * 出生日期
+	 */
+	@Schema(description = "出生日期")
+	private LocalDate birthday;
+	/**
+	 * 民族
+	 */
+	@Schema(description = "民族")
+	private String ethnic;
+	/**
+	 * 所属二级单位
+	 */
+	@Schema(description = "所属二级单位")
+	private String secondaryUnit;
+	/**
+	 * 部门/科室/项目部
+	 */
+	@Schema(description = "部门/科室/项目部")
+	private String department;
+	/**
+	 * 岗位职务
+	 */
+	@Schema(description = "岗位职务")
+	private String post;
+	/**
+	 * 岗位所在地
+	 */
+	@Schema(description = "岗位所在地")
+	private String postLocation;
+	/**
+	 * 用工性质
+	 */
+	@Schema(description = "用工性质")
+	private String nature;
+	/**
+	 * 入职时间
+	 */
+	@Schema(description = "入职时间")
+	private Date hireDate;
+	/**
+	 * 最高学历
+	 */
+	@Schema(description = "最高学历")
+	private String education;
+	/**
+	 * 最高学位
+	 */
+	@Schema(description = "最高学位")
+	private String degree;
+	/**
+	 * 最高学历学校
+	 */
+	@Schema(description = "最高学历学校")
+	private String schoolName;
+	/**
+	 * 最高学历专业名称
+	 */
+	@Schema(description = "最高学历专业名称")
+	private String major;
+	/**
+	 * 职称
+	 */
+	@Schema(description = "职称")
+	private String rank;
+	/**
+	 * 执业资格
+	 */
+	@Schema(description = "执业资格")
+	private String practicingRequirement;
+	/**
+	 * 参研情况
+	 */
+	@Schema(description = "参研情况")
+	private String situation;
+	/**
+	 * 人员类型
+	 */
+	@Schema(description = "人员类型")
+	private String personnelType;
+	/**
+	 * 所属年月
+	 */
+	@Schema(description = "所属年月")
+//	@DateTimeFormat(pattern = "yyyy-MM")
+//	@JsonFormat(pattern = "yyyy-MM")
+	private String yearAndMonth;
+
+	@Schema(description = "情况说明")
+	private String remark;
+
+}

+ 29 - 0
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/vo/TechnicianVO.java

@@ -0,0 +1,29 @@
+
+package org.sky.scientific.pojo.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import org.sky.core.tool.utils.DateUtil;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serial;
+import java.util.Date;
+
+/**
+ * 技术人员花名册 视图实体类
+ *
+ * @author sky
+ * @since 2025-06-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TechnicianVO extends TechnicianEntity {
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+
+
+}

+ 1 - 0
kd-service-api/pom.xml

@@ -20,6 +20,7 @@
         <module>kd-scope-api</module>
         <module>kd-scope-api</module>
         <module>kd-system-api</module>
         <module>kd-system-api</module>
         <module>kd-user-api</module>
         <module>kd-user-api</module>
+        <module>kd-scientific-api</module>
     </modules>
     </modules>
 
 
     <dependencies>
     <dependencies>

+ 15 - 0
kd-service/kd-scientific/Dockerfile

@@ -0,0 +1,15 @@
+FROM kdx/alpine-java:openjdk17_cn_slim
+
+LABEL maintainer="111@qq.com"
+
+RUN mkdir -p /kd/system
+
+WORKDIR /kd/system
+
+EXPOSE 8106
+
+COPY ./target/kd-system.jar ./app.jar
+
+ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
+
+CMD ["--spring.profiles.active=test"]

+ 60 - 0
kd-service/kd-scientific/pom.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>kd-service</artifactId>
+        <groupId>org.sky</groupId>
+        <version>${revision}</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>kd-scientific</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.sky</groupId>
+            <artifactId>kd-core-boot</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.sky</groupId>
+            <artifactId>kd-starter-excel</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.sky</groupId>
+            <artifactId>kd-starter-swagger</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.sky</groupId>
+            <artifactId>kd-scientific-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>io.fabric8</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <configuration>
+                    <skip>${docker.fabric.skip}</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>16</source>
+                    <target>16</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 19 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/ScientificApplication.java

@@ -0,0 +1,19 @@
+package org.sky.scientific;
+
+
+import org.sky.core.cloud.client.KdCloudApplication;
+import org.sky.core.launch.KdApplication;
+import org.sky.core.launch.constant.AppConstant;
+
+/**
+ * 科研模块启动器
+ */
+@KdCloudApplication
+public class ScientificApplication {
+
+	public static void main(String[] args) {
+		KdApplication.run(AppConstant.APPLICATION_SCIENTIFIC_NAME, ScientificApplication.class, args);
+	}
+
+}
+

+ 121 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/TechnicianController.java

@@ -0,0 +1,121 @@
+
+package org.sky.scientific.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import lombok.AllArgsConstructor;
+import org.sky.core.boot.ctrl.KdController;
+import org.sky.core.excel.util.ExcelUtil;
+import org.sky.core.mp.support.Condition;
+import org.sky.core.mp.support.Query;
+import org.sky.core.secure.KdUser;
+import org.sky.core.secure.annotation.IsAdmin;
+import org.sky.core.secure.utils.AuthUtil;
+import org.sky.core.tool.api.R;
+import org.sky.core.tool.constant.KdConstant;
+import org.sky.core.tool.utils.DateUtil;
+import org.sky.core.tool.utils.Func;
+import org.sky.scientific.excel.TechnicianExcel;
+import org.sky.scientific.excel.TechnicianImporter;
+import org.sky.scientific.pojo.dto.TechnicianDTO;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import org.sky.scientific.pojo.vo.TechnicianVO;
+import org.sky.scientific.service.ITechnicianService;
+import org.sky.scientific.wrapper.TechnicianWrapper;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 技术人员花名册 控制器
+ *
+ * @author sky
+ * @since 2025-06-10
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/technician")
+@Tag(name = "技术人员花名册", description = "技术人员花名册接口")
+public class TechnicianController extends KdController {
+
+	private final ITechnicianService technicianService;
+
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 3)
+	@Operation(summary = "分页", description = "传入technician")
+	public R<IPage<TechnicianVO>> page(TechnicianDTO technician, Query query) {
+		IPage<TechnicianVO> pages = technicianService.selectTechnicianPage(Condition.getPage(query), technician);
+		return R.data(pages);
+	}
+
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@Operation(summary = "详情", description = "传入technician")
+	public R<TechnicianVO> detail(TechnicianEntity technician) {
+		TechnicianEntity detail = technicianService.getOne(Condition.getQueryWrapper(technician));
+		return R.data(TechnicianWrapper.build().entityVO(detail));
+	}
+
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@Operation(summary = "新增", description = "传入technician")
+	public R save(@Valid @RequestBody TechnicianDTO technician) {
+		return R.status(technicianService.saveTechnician(technician));
+	}
+
+//	@IsAdmin
+	@PostMapping("import")
+	@ApiOperationSupport(order = 12)
+	@Operation(summary = "导入", description = "传入excel")
+	public R importUser(MultipartFile file, String yearAndMonth) {
+		TechnicianImporter importer = new TechnicianImporter(technicianService, yearAndMonth);
+		ExcelUtil.save(file, importer, TechnicianExcel.class);
+		return R.success("操作成功");
+	}
+
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@Operation(summary = "修改", description = "传入technician")
+	public R update(@Valid @RequestBody TechnicianEntity technician) {
+		return R.status(technicianService.updateTechnician(technician));
+	}
+
+	@PostMapping("/add")
+	@ApiOperationSupport(order = 6)
+	@Operation(summary = "新增", description = "传入technician")
+	public R submit(@Valid @RequestBody TechnicianDTO technician) {
+		return R.status(technicianService.saveTechnician(technician));
+	}
+
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@Operation(summary = "逻辑删除", description = "传入ids")
+	public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(technicianService.deleteLogic(Func.toLongList(ids)));
+	}
+
+//	@IsAdmin
+	@PostMapping("/export")
+	@ApiOperationSupport(order = 9)
+	@Operation(summary = "导出数据", description = "传入technician")
+	public void exportTechnician(@RequestBody TechnicianDTO technician, HttpServletResponse response) {
+		List<TechnicianExcel> list = technicianService.exportTechnician(technician);
+		ExcelUtil.export(response, "技术人员花名册数据" + DateUtil.time(), "技术人员花名册数据表", list, TechnicianExcel.class);
+	}
+
+	@GetMapping("/fetchLastMonthData")
+	@ApiOperationSupport(order = 10)
+	@Operation(summary = "读取上个月人员名单")
+	public R fetchLastMonthData(TechnicianDTO technician) {
+		return R.status(technicianService.fetchLastMonthData(technician));
+	}
+
+}

+ 168 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/TechnicianExcel.java

@@ -0,0 +1,168 @@
+
+package org.sky.scientific.excel;
+
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.write.style.HeadStyle;
+import lombok.Data;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import java.io.Serializable;
+import java.io.Serial;
+import java.time.LocalDate;
+import java.util.Date;
+
+
+/**
+ * 技术人员花名册 Excel实体类
+ *
+ * @author Kd
+ * @since 2025-06-11
+ */
+@Data
+@ColumnWidth(25)
+@HeadRowHeight(20)
+@ContentRowHeight(18)
+//@HeadStyle(fillBackgroundColor = )
+public class TechnicianExcel implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 姓名
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("姓名")
+	private String name;
+	/**
+	 * 工号
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("工号")
+	private String number;
+	/**
+	 * 身份证号码
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("身份证号")
+	private String identityCard;
+	/**
+	 * 性别,1:男,2:女
+	 */
+
+	@ExcelIgnore
+	private Integer gender;
+
+	@ColumnWidth(20)
+	@ExcelProperty("性别")
+	private String genderName;
+	/**
+	 * 出生日期
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("出生日期")
+	private LocalDate birthday;
+	/**
+	 * 民族
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("民族")
+	private String ethnic;
+	/**
+	 * 所属二级单位
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("所属二级单位")
+	private String secondaryUnit;
+	/**
+	 * 部门/科室/项目部
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("部门/科室/项目部")
+	private String department;
+	/**
+	 * 岗位职务
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("岗位职务")
+	private String post;
+	/**
+	 * 岗位所在地
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("岗位所在地")
+	private String postLocation;
+	/**
+	 * 用工性质
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("用工性质")
+	private String nature;
+	/**
+	 * 入职时间
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("入职时间")
+	private Date hireDate;
+	/**
+	 * 最高学历
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("最高学历")
+	private String education;
+	/**
+	 * 最高学位
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("最高学位")
+	private String degree;
+	/**
+	 * 最高学历学校
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("最高学历学校")
+	private String schoolName;
+	/**
+	 * 最高学历专业名称
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("最高学历专业名称")
+	private String major;
+	/**
+	 * 职称
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("职称")
+	private String rank;
+	/**
+	 * 执业资格
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("执业资格")
+	private String practicingRequirement;
+
+	/**
+	 * 其他说明
+	 */
+	@ColumnWidth(50)
+	@ExcelProperty("情况说明")
+	private String remark;
+
+	/**
+	 * 参研情况
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("参研情况")
+	private String situation;
+	/**
+	 * 人员类型
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("人员类型")
+	private String personnelType;
+
+}

+ 23 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/TechnicianImporter.java

@@ -0,0 +1,23 @@
+package org.sky.scientific.excel;
+
+import lombok.RequiredArgsConstructor;
+import org.sky.core.excel.support.ExcelImporter;
+import org.sky.scientific.service.ITechnicianService;
+
+import java.util.List;
+
+
+/**
+ * 用户数据导入类
+ */
+@RequiredArgsConstructor
+public class TechnicianImporter implements ExcelImporter<TechnicianExcel> {
+
+	private final ITechnicianService service;
+	private final String yearAndMonth;
+
+	@Override
+	public void save(List<TechnicianExcel> data) {
+		service.importTechnician(data, yearAndMonth);
+	}
+}

+ 38 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/TechnicianMapper.java

@@ -0,0 +1,38 @@
+
+package org.sky.scientific.mapper;
+
+import org.sky.scientific.pojo.dto.TechnicianDTO;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import org.sky.scientific.pojo.vo.TechnicianVO;
+import org.sky.scientific.excel.TechnicianExcel;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+/**
+ * 技术人员花名册 Mapper 接口
+ *
+ * @author Kd
+ * @since 2025-06-11
+ */
+public interface TechnicianMapper extends BaseMapper<TechnicianEntity> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page 分页参数
+	 * @param technician 查询参数
+	 * @return List<TechnicianVO>
+	 */
+	List<TechnicianVO> selectTechnicianPage(IPage page, TechnicianDTO technician);
+
+	List<TechnicianExcel> exportTechnicianList(@Param("technician") TechnicianDTO technician);
+
+
+	Integer countByDateAndNumberOrIdentityCard(TechnicianEntity technician);
+
+	List<TechnicianEntity> selectByYearAndMonth(String yearAndMonth);
+
+}

+ 139 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/TechnicianMapper.xml

@@ -0,0 +1,139 @@
+<?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="org.sky.scientific.mapper.TechnicianMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="technicianResultMap" type="org.sky.scientific.pojo.entity.TechnicianEntity">
+        <result column="id" property="id"/>
+        <result column="tenant_id" property="tenantId"/>
+        <result column="name" property="name"/>
+        <result column="number" property="number"/>
+        <result column="identity_card" property="identityCard"/>
+        <result column="gender" property="gender"/>
+        <result column="birthday" property="birthday"/>
+        <result column="ethnic" property="ethnic"/>
+        <result column="secondary_unit" property="secondaryUnit"/>
+        <result column="department" property="department"/>
+        <result column="post" property="post"/>
+        <result column="post_location" property="postLocation"/>
+        <result column="nature" property="nature"/>
+        <result column="hire_date" property="hireDate"/>
+        <result column="education" property="education"/>
+        <result column="degree" property="degree"/>
+        <result column="school_name" property="schoolName"/>
+        <result column="major" property="major"/>
+        <result column="rank" property="rank"/>
+        <result column="practicing_requirement" property="practicingRequirement"/>
+        <result column="situation" property="situation"/>
+        <result column="personnel_type" property="personnelType"/>
+        <result column="year_and_month" property="yearAndMonth"/>
+        <result column="remark" property="remark"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+    </resultMap>
+
+
+    <select id="selectTechnicianPage" resultMap="technicianResultMap" parameterType="org.sky.scientific.pojo.dto.TechnicianDTO">
+
+        select *
+        from kd_technician a
+        <if test="technician.yearAndMonth.length()==4">
+            INNER JOIN (
+            SELECT MAX(id) AS max_id FROM kd_technician GROUP BY name,number,identity_card
+            ) b ON a.id = b.max_id
+        </if>
+        where is_deleted = 0
+          <if test="technician.name!=null and technician.name!=''">and name like concat(concat('%', #{technician.name}), '%')</if>
+          <if test="technician.number!=null and technician.number!=''">and name like concat(concat('%', #{technician.number}), '%')</if>
+          <if test="technician.identityCard!=null and technician.identityCard!=''">and identity_card like concat(concat('%', #{technician.identityCard}), '%')</if>
+          <if test="technician.secondaryUnit!=null and technician.secondaryUnit!=''">and secondary_unit like concat(concat('%', #{technician.secondaryUnit}), '%')</if>
+          <if test="technician.department!=null and technician.department!=''">and department like concat(concat('%', #{technician.department}), '%')</if>
+          <if test="technician.post!=null and technician.post!=''">and post like concat(concat('%', #{technician.post}), '%')</if>
+          <if test="technician.postLocation!=null and technician.postLocation!=''">and post_location like concat(concat('%', #{technician.postLocation}), '%')</if>
+          <if test="technician.nature!=null and technician.nature!=''">and nature = #{technician.nature}</if>
+          <if test="technician.education!=null and technician.education!=''">and education = #{technician.education}</if>
+          <if test="technician.degree!=null and technician.degree!=''">and degree = #{technician.degree}</if>
+          <if test="technician.rank!=null and technician.rank!=''">and rank = #{technician.rank}</if>
+          <if test="technician.personnelType!=null and technician.personnelType!=''">and personnel_type = #{technician.personnelType}</if>
+          <if test="technician.situation !=null and technician.situation!=''">and situation = #{technician.situation}</if>
+          <if test="technician.practicingRequirement !=null and technician.practicingRequirement!=''">and practicing_requirement like concat(concat('%', #{technician.practicingRequirement}), '%')</if>
+          <if test="technician.hireStartDate!=null and technician.hireEndDate!=''">and hire_Date between #{technician.hireStartDate} and #{technician.hireEndDate}</if>
+          <choose>
+              <when test="technician.yearAndMonth.length()==4">
+                  and date_format(year_and_month,'%Y') = #{technician.yearAndMonth}
+              </when>
+              <otherwise>
+                  and date_format(year_and_month,'%Y-%m') = #{technician.yearAndMonth}
+              </otherwise>
+          </choose>
+        order by year_and_month
+    </select>
+
+    <select id="exportTechnicianList" resultType="org.sky.scientific.excel.TechnicianExcel" parameterMap="technicianResultMap">
+
+        select *
+        from kd_technician a
+        <if test="technician.yearAndMonth.length()==4">
+            INNER JOIN (
+            SELECT MAX(id) AS max_id FROM kd_technician GROUP BY name,number,identity_card
+            ) b ON a.id = b.max_id
+        </if>
+        where is_deleted = 0
+        <if test="technician.name!=null and technician.name!=''">and name like concat(concat('%', #{technician.name}), '%')</if>
+        <if test="technician.number!=null and technician.number!=''">and name like concat(concat('%', #{technician.number}), '%')</if>
+        <if test="technician.identityCard!=null and technician.identityCard!=''">and identity_card like concat(concat('%', #{technician.identityCard}), '%')</if>
+        <if test="technician.secondaryUnit!=null and technician.secondaryUnit!=''">and secondary_unit like concat(concat('%', #{technician.secondaryUnit}), '%')</if>
+        <if test="technician.department!=null and technician.department!=''">and department like concat(concat('%', #{technician.department}), '%')</if>
+        <if test="technician.post!=null and technician.post!=''">and post like concat(concat('%', #{technician.post}), '%')</if>
+        <if test="technician.postLocation!=null and technician.postLocation!=''">and post_location like concat(concat('%', #{technician.postLocation}), '%')</if>
+        <if test="technician.nature!=null and technician.nature!=''">and nature = #{technician.nature}</if>
+        <if test="technician.education!=null and technician.education!=''">and education = #{technician.education}</if>
+        <if test="technician.degree!=null and technician.degree!=''">and degree = #{technician.degree}</if>
+        <if test="technician.rank!=null and technician.rank!=''">and rank = #{technician.rank}</if>
+        <if test="technician.personnelType!=null and technician.personnelType!=''">and personnel_type = #{technician.personnelType}</if>
+        <if test="technician.situation !=null and technician.situation!=''">and situation = #{technician.situation}</if>
+        <if test="technician.practicingRequirement !=null and technician.practicingRequirement!=''">and practicing_requirement like concat(concat('%', #{technician.practicingRequirement}), '%')</if>
+        <if test="technician.hireStartDate!=null and technician.hireEndDate!=''">and hire_Date between #{technician.hireStartDate} and #{technician.hireEndDate}</if>
+        <choose>
+            <when test="technician.yearAndMonth.length()==4">
+                and date_format(year_and_month,'%Y') = #{technician.yearAndMonth}
+            </when>
+            <otherwise>
+                and date_format(year_and_month,'%Y-%m') = #{technician.yearAndMonth}
+            </otherwise>
+        </choose>
+        order by year_and_month
+    </select>
+
+    <select id="selectByYearAndMonth">
+        select * from kd_technician
+        where is_deleted = 0 and date_format(year_and_month,'%Y-%m') = #{yearAndMonth}
+
+    </select>
+
+    <select id="exportTechnician" resultType="org.sky.scientific.excel.TechnicianExcel">
+        SELECT *
+        FROM kd_technician ${ew.customSqlSegment}
+    </select>
+
+    <select id="countByDateAndNumberOrIdentityCard" parameterType="org.sky.scientific.pojo.entity.TechnicianEntity">
+        select count(*)
+        from kd_technician
+        where is_deleted = 0
+        <choose>
+            <when test="yearAndMonth.length()==4">
+                and date_format(year_and_month,'%Y') = #{yearAndMonth}
+            </when>
+            <otherwise>
+                and date_format(year_and_month,'%Y-%m') = #{yearAndMonth}
+            </otherwise>
+        </choose>
+        and (number = #{number} or identity_card = #{identityCard})
+    </select>
+
+</mapper>

+ 65 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/ITechnicianService.java

@@ -0,0 +1,65 @@
+package org.sky.scientific.service;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import org.sky.scientific.pojo.dto.TechnicianDTO;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import org.sky.scientific.pojo.vo.TechnicianVO;
+import org.sky.scientific.excel.TechnicianExcel;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.sky.core.mp.base.BaseService;
+import java.util.List;
+
+/**
+ * 技术人员花名册 服务类
+ *
+ * @author sky
+ * @since 2025-06-10
+ */
+public interface ITechnicianService extends BaseService<TechnicianEntity> {
+
+	/**
+	 * 新增
+	 * @param technician
+	 * @return
+	 */
+	boolean saveTechnician(TechnicianEntity technician);
+
+	/**
+	 * 修改
+	 * @param technician
+	 * @return
+	 */
+	boolean updateTechnician(TechnicianEntity technician);
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page 分页参数
+	 * @param technician 查询参数
+	 * @return IPage<TechnicianVO>
+	 */
+	IPage<TechnicianVO> selectTechnicianPage(IPage<TechnicianVO> page, TechnicianDTO technician);
+
+
+	/**
+	 * 导出数据
+	 *
+	 * @param technician 查询条件
+	 * @return List<TechnicianExcel>
+	 */
+	List<TechnicianExcel> exportTechnician(TechnicianDTO technician);
+
+	/**
+	 * 导入
+	 * @param data
+	 * @param yearAndMonth 月份,2025-05
+	 */
+	void importTechnician(List<TechnicianExcel> data, String yearAndMonth);
+
+	/**
+	 * 读取上个月人员名单
+	 * @param technician
+	 * @return
+	 */
+	boolean fetchLastMonthData(TechnicianEntity technician);
+}

+ 100 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/TechnicianServiceImpl.java

@@ -0,0 +1,100 @@
+
+package org.sky.scientific.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.sky.core.log.exception.ServiceException;
+import org.sky.core.mp.base.BaseServiceImpl;
+import org.sky.core.tool.utils.BeanUtil;
+import org.sky.core.tool.utils.DateUtil;
+import org.sky.core.tool.utils.StringUtil;
+import org.sky.scientific.excel.TechnicianExcel;
+import org.sky.scientific.mapper.TechnicianMapper;
+import org.sky.scientific.pojo.dto.TechnicianDTO;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import org.sky.scientific.pojo.vo.TechnicianVO;
+import org.sky.scientific.service.ITechnicianService;
+import org.sky.system.cache.DictCache;
+import org.sky.system.pojo.enums.DictEnum;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 技术人员花名册 服务实现类
+ *
+ * @author sky
+ * @since 2025-06-10
+ */
+@Service
+public class TechnicianServiceImpl extends BaseServiceImpl<TechnicianMapper, TechnicianEntity> implements ITechnicianService {
+
+	@Override
+	public boolean saveTechnician(TechnicianEntity technician) {
+		//检查重复性
+		check(technician);
+		technician.setYearAndMonth(technician.getYearAndMonth() + "-01");
+		return this.save(technician);
+	}
+
+	@Override
+	public boolean updateTechnician(TechnicianEntity technician) {
+		return this.updateById(technician);
+	}
+
+	@Override
+	public IPage<TechnicianVO> selectTechnicianPage(IPage<TechnicianVO> page, TechnicianDTO technician) {
+		return page.setRecords(baseMapper.selectTechnicianPage(page, technician));
+	}
+
+
+	@Override
+	public List<TechnicianExcel> exportTechnician(TechnicianDTO technician) {
+		List<TechnicianExcel> technicianList = baseMapper.exportTechnicianList(technician);
+		technicianList.forEach(temp -> {
+			temp.setGenderName(DictCache.getValue(DictEnum.SEX, temp.getGender()));
+		});
+		return technicianList;
+	}
+
+	@Transactional
+	@Override
+	public void importTechnician(List<TechnicianExcel> data, String yearAndMonth) {
+		for (TechnicianExcel excel : data) {
+			TechnicianEntity technician = Objects.requireNonNull(BeanUtil.copyProperties(excel, TechnicianDTO.class));
+			//转换 性别字典
+			technician.setGender(Integer.valueOf(DictCache.getKey(DictEnum.SEX, excel.getGenderName())));
+			technician.setYearAndMonth(yearAndMonth);
+			this.saveTechnician(technician);
+		}
+	}
+
+	@Transactional
+	@Override
+	public boolean fetchLastMonthData(TechnicianEntity technician) {
+		//查询上个月的数据
+		//得到上个月的年月
+		String lastDate = DateUtil.format(DateUtil.minusMonths(DateUtil.parse(technician.getYearAndMonth(), DateUtil.PATTERN_YYYY_MM), 1), DateUtil.PATTERN_YYYY_MM);
+		List<TechnicianEntity> lastMonthList = this.baseMapper.selectByYearAndMonth(lastDate);
+		//与本月数据对比,去重后保存至数据库
+		for (TechnicianEntity temp : lastMonthList) {
+			temp.setYearAndMonth(technician.getYearAndMonth());
+			temp.setId(null);
+			saveTechnician(temp);
+		}
+		return true;
+	}
+
+	private void check(TechnicianEntity technician) {
+		if (StringUtil.isBlank(technician.getYearAndMonth())) {
+			technician.setYearAndMonth(DateUtil.format(DateUtil.now(), DateUtil.PATTERN_YYYY_MM));
+		}
+		//根据 年月 和工号或身份证 查询是否存在,存在则本次导入所有的数据都不成功
+		Integer count = this.baseMapper.countByDateAndNumberOrIdentityCard(technician);
+		if (count > 0) {
+			throw new ServiceException("导入失败,姓名:[" + technician.getName() + "]已存在,请检查数据");
+		}
+	}
+}

+ 35 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/wrapper/TechnicianWrapper.java

@@ -0,0 +1,35 @@
+
+package org.sky.scientific.wrapper;
+
+import org.sky.core.mp.support.BaseEntityWrapper;
+import org.sky.core.tool.utils.BeanUtil;
+import org.sky.scientific.pojo.entity.TechnicianEntity;
+import org.sky.scientific.pojo.vo.TechnicianVO;
+import java.util.Objects;
+
+/**
+ * 技术人员花名册 包装类,返回视图层所需的字段
+ *
+ * @author sky
+ * @since 2025-06-10
+ */
+public class TechnicianWrapper extends BaseEntityWrapper<TechnicianEntity, TechnicianVO> {
+
+	public static TechnicianWrapper build() {
+		return new TechnicianWrapper();
+ 	}
+
+	@Override
+	public TechnicianVO entityVO(TechnicianEntity technician) {
+		TechnicianVO technicianVO = Objects.requireNonNull(BeanUtil.copyProperties(technician, TechnicianVO.class));
+
+		//User createUser = UserCache.getUser(technician.getCreateUser());
+		//User updateUser = UserCache.getUser(technician.getUpdateUser());
+		//technicianVO.setCreateUserName(createUser.getName());
+		//technicianVO.setUpdateUserName(updateUser.getName());
+
+		return technicianVO;
+	}
+
+
+}

+ 10 - 0
kd-service/kd-scientific/src/main/resources/application-dev.yml

@@ -0,0 +1,10 @@
+#服务器端口
+server:
+  port: 8200
+
+#数据源配置
+spring:
+  datasource:
+    url: ${kd.datasource.dev.url}
+    username: ${kd.datasource.dev.username}
+    password: ${kd.datasource.dev.password}

+ 10 - 0
kd-service/kd-scientific/src/main/resources/application-prod.yml

@@ -0,0 +1,10 @@
+#服务器端口
+server:
+  port: 8200
+
+#数据源配置
+spring:
+  datasource:
+    url: ${kd.datasource.prod.url}
+    username: ${kd.datasource.prod.username}
+    password: ${kd.datasource.prod.password}

+ 10 - 0
kd-service/kd-scientific/src/main/resources/application-test.yml

@@ -0,0 +1,10 @@
+#服务器端口
+server:
+  port: 8200
+
+#数据源配置
+spring:
+  datasource:
+    url: ${kd.datasource.test.url}
+    username: ${kd.datasource.test.username}
+    password: ${kd.datasource.test.password}

+ 2 - 2
kd-service/kd-system/src/main/java/org/sky/system/mapper/DictBizMapper.xml

@@ -26,11 +26,11 @@
     <select id="getValue" resultType="java.lang.String">
     <select id="getValue" resultType="java.lang.String">
         select
         select
             dict_value
             dict_value
-        from kd_dict_biz where tenant_id = #{param1} and code = #{param2} and dict_key = #{param3} and is_deleted = 0
+        from kd_dict_biz where code = #{param2} and dict_key = #{param3} and is_deleted = 0
     </select>
     </select>
 
 
     <select id="getList" resultMap="dictResultMap">
     <select id="getList" resultMap="dictResultMap">
-        select id, tenant_id, parent_id, code, dict_key, dict_value, sort, remark from kd_dict_biz where tenant_id = #{param1} and code = #{param2} and parent_id > 0 and is_sealed = 0 and is_deleted = 0
+        select id, tenant_id, parent_id, code, dict_key, dict_value, sort, remark from kd_dict_biz where code = #{param2} and parent_id > 0 and is_sealed = 0 and is_deleted = 0
     </select>
     </select>
 
 
     <select id="tree" resultMap="treeNodeResultMap">
     <select id="tree" resultMap="treeNodeResultMap">

+ 1 - 0
kd-service/pom.xml

@@ -31,6 +31,7 @@
     <modules>
     <modules>
         <module>kd-desk</module>
         <module>kd-desk</module>
         <module>kd-system</module>
         <module>kd-system</module>
+        <module>kd-scientific</module>
     </modules>
     </modules>
 
 
     <dependencies>
     <dependencies>

+ 11 - 1
pom.xml

@@ -9,7 +9,7 @@
     <packaging>pom</packaging>
     <packaging>pom</packaging>
 
 
     <properties>
     <properties>
-        <revision>2.0.0.RELEASE</revision>
+        <revision>2.0.1.RELEASE</revision>
 
 
         <java.version>17</java.version>
         <java.version>17</java.version>
         <maven.plugin.version>3.11.0</maven.plugin.version>
         <maven.plugin.version>3.11.0</maven.plugin.version>
@@ -50,6 +50,11 @@
                 <artifactId>kd-common</artifactId>
                 <artifactId>kd-common</artifactId>
                 <version>${revision}</version>
                 <version>${revision}</version>
             </dependency>
             </dependency>
+            <dependency>
+                <groupId>org.sky</groupId>
+                <artifactId>kd-scientific</artifactId>
+                <version>${revision}</version>
+            </dependency>
              <dependency>
              <dependency>
                 <groupId>org.sky</groupId>
                 <groupId>org.sky</groupId>
                 <artifactId>kd-dict-api</artifactId>
                 <artifactId>kd-dict-api</artifactId>
@@ -85,6 +90,11 @@
                 <artifactId>kd-system-api</artifactId>
                 <artifactId>kd-system-api</artifactId>
                 <version>${revision}</version>
                 <version>${revision}</version>
             </dependency>
             </dependency>
+            <dependency>
+                <groupId>org.sky</groupId>
+                <artifactId>kd-scientific-api</artifactId>
+                <version>${revision}</version>
+            </dependency>
         </dependencies>
         </dependencies>
     </dependencyManagement>
     </dependencyManagement>