first commit

This commit is contained in:
lcj
2025-07-23 16:38:10 +08:00
commit 33423fc4d2
1640 changed files with 153857 additions and 0 deletions

View File

@ -0,0 +1,216 @@
<?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>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-system</artifactId>
<description>
system系统模块
</description>
<dependencies>
<!-- JSON解析FastJSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<!-- word转pdf转图片 -->
<!-- docx4j 核心 -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-core</artifactId>
<version>11.5.3</version>
</dependency>
<!-- JAXB 引擎 -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
<version>11.5.3</version>
</dependency>
<!-- XSL-FO 输出 PDF -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>11.5.3</version>
<exclusions>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- PDF 渲染用的 PDFBox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.29</version>
</dependency>
<!-- 必须配套引入 fontbox否则运行时报错 -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>2.0.29</version>
</dependency>
<!-- word 模版导出 poi-tl 模板引擎 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version> <!-- 建议使用最新版本 -->
</dependency>
<!-- 在pdf上生成二维码 -->
<!-- 支持中文字体 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!-- iText -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<!-- ZXing -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId>
</dependency>
<!-- OSS功能模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-oss</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<!-- excel-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-excel</artifactId>
</dependency>
<!-- SMS功能模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sms</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-security</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-web</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sensitive</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-encrypt</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sse</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-jts</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-workflow</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.13.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.15.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,28 @@
package org.dromara.common.constant;
import java.io.File;
/**
* @author lilemy
* @date 2025/4/23 11:09
*/
public interface DesignMapFileConstant {
String DXF_BASE_PATH = "file" + File.separator + "resource" + File.separator + "design";
/**
* WGS 84
*/
String EPSG4326 = "4326";
String EPSG4524 = "4524";
String DXFFileSuffix = "dxf";
String JSONFileSuffix = "json";
static String getDxfProjectPath(Long projectId) {
return DXF_BASE_PATH + File.separator + projectId;
}
}

View File

@ -0,0 +1,15 @@
package org.dromara.common.constant;
/**
* @author lilemy
* @date 2025/4/24 17:44
*/
public interface GeoJsonConstant {
String POINT = "Point";
String LINE = "LineString";
String POLYGON = "Polygon";
}

View File

@ -0,0 +1,14 @@
package org.dromara.common.constant;
/**
* @Author: Cory·铁憨憨
* @Date: 2025-07-03-14:12
* @Description: minio存储路线
*/
public interface MinioPathConstant {
// 联系单
String ContactNotice = "contactNotice";
// 联系单模板
String ContactNoticeTemplate = "contactNotice/template";
}

View File

@ -0,0 +1,9 @@
package org.dromara.common.constant;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:38
* @Version 1.0
*/public interface businessConstant {
String REDIS_BAIDU_KEY = "baidu:access_token"; //百度token存储在redis中的key
}

View File

@ -0,0 +1,24 @@
package org.dromara.common.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025/4/14 14:03
*/
@Getter
public enum DocumentStatusEnum {
NORMAL("正常", "0"),
DELETE("删除", "1");
private final String text;
private final String value;
DocumentStatusEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,25 @@
package org.dromara.common.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025/4/14 10:42
*/
@Getter
public enum DocumentTypeEnum {
FOLDER("文件夹", "1"),
FILE("文件", "2"),
PICTURE("图片", "3");
private final String text;
private final String value;
DocumentTypeEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,26 @@
package org.dromara.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author lilemy
* @date 2025/5/27 9:16
*/
public class BigDecimalUtil {
/**
* 计算百分比
*
* @param dividend 被除数
* @param divisor 除数
* @return 百分比保留2位小数如 12.34%
*/
public static BigDecimal toPercentage(BigDecimal dividend, BigDecimal divisor) {
if (dividend == null || divisor == null || divisor.compareTo(BigDecimal.ZERO) == 0) {
return new BigDecimal(0);
}
return dividend.divide(divisor, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
}
}

View File

@ -0,0 +1,100 @@
package org.dromara.common.utils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author lilemy
* @date 2025/4/17 14:53
*/
public class DocumentUtil {
/**
* 在给定的 run 里插入图片,并按原始大小(或缩放后大小)设置宽高。
*
* @param run 要插入图片的 XWPFRun
* @param imagePath 本地图片路径或 URL这里示例用本地文件
* @param document 当前文档对象
* @param maxWidthPx 最大允许宽度(像素),如果原图更宽就按比例缩放;设置为 <=0 则不缩放
*/
public static void insertImageDynamic(XWPFRun run,
String imagePath,
XWPFDocument document,
int maxWidthPx) throws Exception {
// 1. 先把图片读到 byte[]
byte[] imgBytes = Files.readAllBytes(Paths.get(imagePath));
// 2. 用 ImageIO 读出宽高(像素)
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgBytes));
int widthPx = img.getWidth();
int heightPx = img.getHeight();
// 3. 如果指定了最大宽度,而且原图更宽,则按比例缩放
if (maxWidthPx > 0 && widthPx > maxWidthPx) {
double ratio = (double) maxWidthPx / widthPx;
widthPx = maxWidthPx;
heightPx = (int) (heightPx * ratio);
}
// 4. 把像素转换成 EMU
int widthEmu = Units.pixelToEMU(widthPx);
int heightEmu = Units.pixelToEMU(heightPx);
// 5. 插入图片
String lower = imagePath.toLowerCase();
int format = lower.endsWith(".png") ? XWPFDocument.PICTURE_TYPE_PNG
: lower.endsWith(".gif") ? XWPFDocument.PICTURE_TYPE_GIF
: lower.endsWith(".jpeg") ? XWPFDocument.PICTURE_TYPE_JPEG
: lower.endsWith(".jpg") ? XWPFDocument.PICTURE_TYPE_JPEG
: XWPFDocument.PICTURE_TYPE_PNG; // 默认当 PNG
try (InputStream picIn = new ByteArrayInputStream(imgBytes)) {
run.addPicture(picIn, format, imagePath, widthEmu, heightEmu);
}
}
/**
* 递归将 sourceDir 中的所有文件和子目录,按照相对于 rootDir 的路径写入 ZipOutputStream。
*
* @param rootDir 源目录的根,用来计算相对路径
* @param sourceDir 当前递归到的目录
* @param zos ZIP 输出流
*/
public static void zipDirectory(Path rootDir, Path sourceDir, ZipOutputStream zos) throws IOException {
// 遍历当前目录下的所有文件和文件夹
try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
// 如果是目录,递归
zipDirectory(rootDir, entry, zos);
} else {
// 如果是文件,创建一个 ZipEntry路径以 '/' 分隔
Path relativePath = rootDir.relativize(entry);
String zipEntryName = relativePath.toString().replace(File.separatorChar, '/');
ZipEntry zipEntry = new ZipEntry(zipEntryName);
zos.putNextEntry(zipEntry);
// 把文件内容写入 ZIP
try (InputStream is = Files.newInputStream(entry)) {
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) != -1) {
zos.write(buffer, 0, len);
}
}
zos.closeEntry();
}
}
}
}
}

View File

@ -0,0 +1,97 @@
package org.dromara.common.utils;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
/**
* @author lilemy
* @date 2025/4/23 10:42
*/
@Slf4j
public class Dxf2JsonUtil {
/**
* dxf转json
*
* @param exePath dxf2json.exe路径
* @param inputDXFPath 输入dxf文件路径
* @param outputJSONPath 输出json文件路径
* @param sourceEPSG 源坐标系
* @param targetEPSG 目标坐标系
*/
public static void dxf2json(String exePath, String inputDXFPath, String outputJSONPath, String sourceEPSG, String targetEPSG) {
// 判断对应文件是否存在
File exeFile = new File(exePath);
if (!exeFile.exists()) {
throw new ServiceException("转换程序不存在!");
}
File inputDXFFile = new File(inputDXFPath);
if (!inputDXFFile.exists()) {
throw new ServiceException("待转换 dxf 文件不存在!");
}
// 构造命令行参数
List<String> parameters = buildParameter(exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG);
// 执行命令行
ProcessBuilder builder = new ProcessBuilder(parameters);
// 合并标准错误和输出
builder.redirectErrorStream(true);
try {
Process process = builder.start();
// 读取输出
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), "GBK")
);
String line;
log.info("dxf 转 json 程序开始执行,程序路径:{},输入 dxf 路径:{},输出 json 文件路径:{},源坐标系:{},模板坐标系:{}",
exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG);
while ((line = reader.readLine()) != null) {
log.info("dxf 转 json 程序执行中:{}", line);
JSONObject jsonObject = JSONUtil.parseObj(line);
Integer code = jsonObject.get("code", Integer.class);
if (code != 0 && code != 200) {
throw new ServiceException("dxf 转 json 程序执行出错!");
}
}
int exitCode = process.waitFor();
log.info("dxf 转 json 程序执行完毕,程序退出码:{}", exitCode);
reader.close();
} catch (IOException | InterruptedException e) {
log.error("执行 dxf 转 json 命令行时出错", e);
}
}
/**
* 构造命令行参数
*
* @param exePath dxf2json.exe路径
* @param inputDXFPath 输入dxf文件路径
* @param outputJSONPath 输出json文件路径
* @param sourceEPSG 源坐标系
* @param targetEPSG 目标坐标系
* @return 命令行参数
*/
public static List<String> buildParameter(String exePath,
String inputDXFPath,
String outputJSONPath,
String sourceEPSG,
String targetEPSG) {
// 构造命令行
return Arrays.asList(
exePath,
inputDXFPath,
outputJSONPath,
sourceEPSG,
targetEPSG
);
}
}

View File

@ -0,0 +1,24 @@
package org.dromara.common.utils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.http.HttpClient;
import java.time.Duration;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:16
* @Version 1.0
*
* HttpClient 设计为可重用、线程安全的组件,其内部维护了连接池等资源,适合在多个接口调用中共享使用,所以交给Spring Bean 管理
*/
@Configuration
public class HttpClientConfig {
@Bean
public HttpClient httpClient() {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
}
}

View File

@ -0,0 +1,51 @@
package org.dromara.common.utils;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author lilemy
* @date 2025/6/25 10:57
*/
@Slf4j
@Component
public class IdCardEncryptorUtil {
@Value("${id-card.encrypt-key}")
private String encryptKeyHex;
private AES aes;
@PostConstruct
public void init() {
byte[] keyBytes = HexUtil.decodeHex(encryptKeyHex);
this.aes = SecureUtil.aes(keyBytes);
log.info("身份证 AES 加解密工具初始化成功");
}
/**
* 加密
*
* @param idCard 身份证号码
* @return 加密后的身份证号码
*/
public String encrypt(String idCard) {
return aes.encryptBase64(idCard);
}
/**
* 解密
*
* @param encrypted 密文
* @return 解密后的身份证号码
*/
public String decrypt(String encrypted) {
return aes.decryptStr(encrypted);
}
}

View File

@ -0,0 +1,270 @@
package org.dromara.common.utils;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.constant.GeoJsonConstant;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPlane;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint;
import org.dromara.facility.domain.dto.geojson.FacGeometry;
import org.dromara.facility.domain.dto.geojson.FacGeometryByPoint;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.index.strtree.STRtree;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author lilemy
* @date 2025/4/24 11:48
*/
public class JSTUtil {
private static final GeometryFactory geometryFactory = new GeometryFactory();
/**
* 获取最近点的名称
*
* @param target 目标点
* @param nameGeoJson 点对象列表
* @return 最近点的名称
*/
public static String findNearestText(List<Double> target, List<FacFeatureByPoint> nameGeoJson) {
Point targetPoint = geometryFactory.createPoint(new Coordinate(target.get(0), target.get(1)));
FacFeatureByPoint nearestFeature = null;
double minDistance = Double.MAX_VALUE;
for (FacFeatureByPoint feature : nameGeoJson) {
FacGeometryByPoint geometry = feature.getGeometry();
List<Double> coords = geometry.getCoordinates();
if (coords != null && coords.size() == 2) {
Point currentPoint = geometryFactory.createPoint(new Coordinate(coords.get(0), coords.get(1)));
double distance = targetPoint.distance(currentPoint);
if (distance < minDistance) {
minDistance = distance;
nearestFeature = feature;
}
}
}
if (nearestFeature != null && nearestFeature.getProperties() != null) {
return nearestFeature.getProperties().getText();
}
return null; // 如果没找到合适的点
}
/**
* 点是否在平面内
*
* @param planeLists 平面坐标
* @param pointList 点坐标
* @return 点是否在平面内
*/
public static Boolean pointIsWithInPlane(List<List<Double>> planeLists, List<Double> pointList) {
// 构建平面
Coordinate[] coordinates = getPlaneCoordinate(planeLists);
Polygon polygon = geometryFactory.createPolygon(coordinates);
// 构建待判断点
Point point = geometryFactory.createPoint(new Coordinate(pointList.get(0), pointList.get(1)));
// 判断是否在多边形内
return polygon.contains(point);
}
/**
* 获取平面内点列表集合
*
* @param planeLists 平面坐标列表
* @param pointLists 点坐标列表集合
* @return 平面内点坐标列表集合
*/
public static List<List<Double>> getPointInPlaneList(List<List<Double>> planeLists, List<List<Double>> pointLists) {
// 构建平面
Coordinate[] coordinates = getPlaneCoordinate(planeLists);
LinearRing shell = geometryFactory.createLinearRing(coordinates);
Polygon polygon = geometryFactory.createPolygon(shell);
// 获取平面内点结合
return pointLists.stream().filter(pointList -> {
// 构建待判断点
Point point = geometryFactory.createPoint(new Coordinate(pointList.get(0), pointList.get(1)));
// 判断是否在多边形内
return polygon.contains(point);
}).toList();
}
/**
* 平面是否在平面内
*
* @param referencePlane 参考平面
* @param comparePlane 比较平面
* @return 平面是否在平面内
*/
public static Boolean planeIsWithInPlane(List<List<Double>> referencePlane, List<List<Double>> comparePlane) {
// 构建参考平面
Coordinate[] referenceCoordinates = getPlaneCoordinate(referencePlane);
Polygon referencePolygon = geometryFactory.createPolygon(referenceCoordinates);
// 构建比较平面
Coordinate[] compareCoordinates = getPlaneCoordinate(comparePlane);
Polygon comparePolygon = geometryFactory.createPolygon(compareCoordinates);
// 判断是否在多边形内
return referencePolygon.contains(comparePolygon);
}
/**
* 判断两个平面是否相交
*
* @param referencePlane 参考平面
* @param comparePlane 待比较平面
* @return 平面是否相交
*/
public static Boolean arePolygonsIntersecting(List<List<Double>> referencePlane, List<List<Double>> comparePlane) {
// 构建 Polygon A参考面
Coordinate[] coordsA = referencePlane.stream()
.map(p -> new Coordinate(p.getFirst(), p.get(1)))
.toArray(Coordinate[]::new);
Polygon polygonA = geometryFactory.createPolygon(coordsA);
// 构建 Polygon B比较面
Coordinate[] coordsB = comparePlane.stream()
.map(p -> new Coordinate(p.getFirst(), p.get(1)))
.toArray(Coordinate[]::new);
Polygon polygonB = geometryFactory.createPolygon(coordsB);
// 使用 JTS 判断是否相交
return polygonA.intersects(polygonB);
}
/**
* 获取平面坐标数组
*
* @param planeLists 平面坐标列表
* @return 平面坐标数组
*/
public static Coordinate[] getPlaneCoordinate(List<List<Double>> planeLists) {
return planeLists.stream().map(planeList ->
new Coordinate(planeList.getFirst(), planeList.get(1)))
.toList().toArray(new Coordinate[0]);
}
/**
* 获取二维坐标
*
* @param geometry 几何对象
* @return 二维坐标
*/
public static List<List<Double>> getTwoDimensionalCoordinates(FacGeometry geometry) {
String type = geometry.getType();
List<Object> coordinates = geometry.getCoordinates();
return switch (type) {
case GeoJsonConstant.POINT -> throw new ServiceException("点位无法创建方阵", HttpStatus.BAD_REQUEST);
case GeoJsonConstant.LINE -> coordinates.stream()
.filter(obj -> obj instanceof List<?>)
.map(obj -> ((List<?>) obj).stream()
.filter(num -> num instanceof Number)
.map(num -> ((Number) num).doubleValue())
.collect(Collectors.toList()))
.collect(Collectors.toList());
case GeoJsonConstant.POLYGON -> coordinates.stream()
.filter(obj -> obj instanceof List<?>)
.flatMap(obj -> ((List<?>) obj).stream())
.filter(pointObj -> pointObj instanceof List<?>)
.map(pointObj -> ((List<?>) pointObj).stream()
.filter(num -> num instanceof Number)
.map(num -> ((Number) num).doubleValue())
.collect(Collectors.toList()))
.collect(Collectors.toList());
default -> throw new ServiceException("暂不支持该类型", HttpStatus.BAD_REQUEST);
};
}
/**
* 匹配最近的点,获取该点的名称
*
* @param polygon 平面
* @param points 点列表集合
* @return 最近点的名称
*/
public static String findNearestPointText(List<List<Double>> polygon, List<FacFeatureByPoint> points) {
if (polygon == null || polygon.size() < 3 || points == null || points.isEmpty()) {
return null;
}
// 1. 构建 Polygon
Coordinate[] polygonCoords = polygon.stream()
.map(coord -> new Coordinate(coord.getFirst(), coord.get(1)))
.toArray(Coordinate[]::new);
Polygon jtsPolygon = geometryFactory.createPolygon(polygonCoords);
// 2. 构建空间索引JTS STRtree
STRtree spatialIndex = new STRtree();
Map<Coordinate, FacFeatureByPoint> coordToFeatureMap = new HashMap<>();
for (FacFeatureByPoint feature : points) {
List<Double> coords = feature.getGeometry().getCoordinates();
if (coords == null || coords.size() != 2) continue;
Coordinate coord = new Coordinate(coords.get(0), coords.get(1));
Point point = geometryFactory.createPoint(coord);
// 用点的 Envelope 加入索引
spatialIndex.insert(point.getEnvelopeInternal(), point);
coordToFeatureMap.put(coord, feature);
}
// 3. 查询距离 polygon 最近的点
// 用 polygon 中心点附近构造 Envelope扩大一些范围
Envelope searchEnv = jtsPolygon.getEnvelopeInternal();
searchEnv.expandBy(10); // 扩大搜索半径
@SuppressWarnings("unchecked")
List<Point> candidatePoints = spatialIndex.query(searchEnv);
double minDistance = Double.MAX_VALUE;
Coordinate nearestCoord = null;
for (Point point : candidatePoints) {
double distance = point.distance(jtsPolygon);
if (distance < minDistance) {
minDistance = distance;
nearestCoord = point.getCoordinate();
}
}
if (nearestCoord != null) {
FacFeatureByPoint nearestFeature = coordToFeatureMap.get(nearestCoord);
if (nearestFeature != null && nearestFeature.getProperties() != null) {
return nearestFeature.getProperties().getText();
}
}
return null;
}
/**
* 匹配最近的面,获取该面的信息
*
* @param pointFeature 点位
* @param polygons 平面列表
* @return 最近面的信息
*/
public static FacFeatureByPlane findNearestOrContainingPolygon(
FacFeatureByPoint pointFeature,
List<FacFeatureByPlane> polygons
) {
if (pointFeature == null || polygons == null || polygons.isEmpty()) {
return null;
}
List<Double> coords = pointFeature.getGeometry().getCoordinates();
if (coords == null || coords.size() != 2) return null;
Coordinate pointCoord = new Coordinate(coords.get(0), coords.get(1));
Point point = geometryFactory.createPoint(pointCoord);
FacFeatureByPlane nearestPolygon = null;
double minDistance = Double.MAX_VALUE;
for (FacFeatureByPlane polygonFeature : polygons) {
if (polygonFeature == null || polygonFeature.getGeometry() == null) {
continue; // 跳过空对象
}
List<List<Double>> polyCoords = polygonFeature.getGeometry().getCoordinates().getFirst();
Coordinate[] polygonCoords = polyCoords.stream()
.map(c -> new Coordinate(c.getFirst(), c.get(1)))
.toArray(Coordinate[]::new);
Polygon polygon = geometryFactory.createPolygon(polygonCoords);
// 优先使用包含点的 polygon
if (polygon.contains(point)) {
return polygonFeature;
}
double distance = polygon.distance(point);
if (distance < minDistance) {
minDistance = distance;
nearestPolygon = polygonFeature;
}
}
return nearestPolygon;
}
}

View File

@ -0,0 +1,24 @@
package org.dromara.common.utils;
import cn.hutool.json.JSONArray;
/**
* @author lilemy
* @date 2025/5/30 14:55
*/
public class JsonDimensionUtil {
/**
* 判断 JSONArray 的嵌套维度
*
* @param array 需要判断的 JSONArray
* @return 返回维度层级1 表示一维2 表示二维3 表示三维 ...
*/
public static int getJsonArrayDepth(Object array) {
if (array instanceof JSONArray jsonArray && !jsonArray.isEmpty()) {
return 1 + getJsonArrayDepth(jsonArray.getFirst());
}
return 0;
}
}

View File

@ -0,0 +1,34 @@
package org.dromara.common.utils;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
/**
* @author lilemy
* @date 2025/5/28 11:25
*/
public class PageConvertUtil {
/**
* 将 Page<T> 转换为 Page<V>
*
* @param source 原始分页数据
* @param mapper 实体 -> VO 的转换函数
* @return Page<V>
*/
public static <T, V> Page<V> convert(Page<T> source, Function<T, V> mapper) {
Page<V> target = new Page<>(source.getCurrent(), source.getSize(), source.getTotal());
if (CollUtil.isEmpty(source.getRecords())) {
target.setRecords(Collections.emptyList());
} else {
List<V> voList = source.getRecords().stream().map(mapper).toList();
target.setRecords(voList);
}
return target;
}
}

View File

@ -0,0 +1,142 @@
package org.dromara.common.utils;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author lilemy
* @date 2025/7/7 9:56
*/
public class PdfBoxQrCodeGenerator {
/**
* 生成二维码图片并返回路径
*
* @param text 二维码文本
* @param width 二维码宽度
* @param height 二维码高度
* @param outputPath 二维码图片保存路径
* @return 二维码图片保存路径
*/
public static String generateQRCodeImage(String text, int width, int height, String outputPath) throws Exception {
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height);
MatrixToImageWriter.writeToPath(bitMatrix, "PNG", new File(outputPath).toPath());
return outputPath;
}
/**
* 获取二维码图片字节数组
*
* @param text 二维码文本
* @param width 二维码宽度
* @param height 二维码高度
* @return 二维码图片字节数组
*/
public static byte[] generateQRCodeBytes(String text, int width, int height) {
BufferedImage image = QrCodeUtil.generate(text, width, height);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImgUtil.write(image, ImgUtil.IMAGE_TYPE_PNG, out);
return out.toByteArray();
}
/**
* 获取二维码图片字节数组
*
* @param text 二维码文本
* @return 二维码图片字节数组
*/
public static byte[] generateQRCodeBytes(String text) {
return generateQRCodeBytes(text, 200, 200);
}
/**
* 在PDF指定位置添加二维码
*
* @param srcPdf 原PDF文件路径
* @param destPdf 新PDF文件路径
* @param qrImagePath 二维码图片路径
* @param pageNum 页码
* @param x 坐标
* @param y 坐标
*/
public static void addQRCodeToPDF(String srcPdf, String destPdf, String qrImagePath, int pageNum, float x, float y) throws IOException, DocumentException {
PdfReader reader = new PdfReader(srcPdf);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destPdf));
PdfContentByte content = stamper.getOverContent(pageNum);
Image image = Image.getInstance(qrImagePath);
image.setAbsolutePosition(x, y); // 坐标:左下角为原点
image.scaleAbsolute(100, 100); // 设置二维码大小
content.addImage(image);
stamper.close();
reader.close();
}
/**
* 在PDF指定位置添加二维码
*
* @param srcPdf 原PDF文件路径
* @param destPdf 新PDF文件路径
* @param qrCodeBytes 二维码图片字节数组
* @param pageNum 页码
* @param x 坐标
* @param y 坐标
*/
public static void addQRCodeToPDF(String srcPdf, String destPdf, byte[] qrCodeBytes, int pageNum, float x, float y) throws IOException, DocumentException {
PdfReader reader = new PdfReader(srcPdf);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destPdf));
PdfContentByte content = stamper.getOverContent(pageNum);
Image image = Image.getInstance(qrCodeBytes);
image.setAbsolutePosition(x, y); // 坐标:左下角为原点
image.scaleAbsolute(100, 100); // 设置二维码大小
content.addImage(image);
stamper.close();
reader.close();
}
/**
* 在PDF指定位置添加二维码并返回数据流
*
* @param srcPdf 原PDF文件路径
* @param qrCodeBytes 二维码图片字节数组
* @param pageNum 页码
* @param x 坐标
* @param y 坐标
* @return 插入二维码后的PDF文件流
*/
public static ByteArrayOutputStream addQRCodeToPDF(String srcPdf, byte[] qrCodeBytes, int pageNum, float x, float y) throws IOException, DocumentException {
PdfReader reader = new PdfReader(srcPdf);
ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, pdfOut);
PdfContentByte content = stamper.getOverContent(pageNum);
Image image = Image.getInstance(qrCodeBytes);
image.setAbsolutePosition(x, y); // 坐标:左下角为原点
image.scaleAbsolute(100, 100); // 设置二维码大小
content.addImage(image);
stamper.close();
reader.close();
return pdfOut;
}
}

View File

@ -0,0 +1,101 @@
package org.dromara.common.utils.baiduUtil;
import com.google.gson.Gson;
import org.dromara.common.utils.baiduUtil.entity.AccessTokenResponse;
import org.glassfish.jaxb.runtime.v2.runtime.reflect.opt.Const;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.TimeUnit;
import static org.dromara.common.constant.businessConstant.REDIS_BAIDU_KEY;
/**
* @Author 铁憨憨
* @Date 2025/7/18 9:46
* @Version 1.0
*
* 获取百度AccessToken
*/
@Service
public class BaiDuCommon {
@Autowired
private HttpClient httpClient;
@Autowired
private StringRedisTemplate redisTemplate;
@Value("${baidu.client.id}")
private String clientId;
@Value("${baidu.client.secret}")
private String clientSecret;
private static final String TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token?client_id=%s&client_secret=%s&grant_type=client_credentials";
private static final Gson gson = new Gson();
/**
* 获取百度AccessToken优先从Redis缓存中获取
*/
public String getAccessToken() {
// 1. 尝试从Redis中获取
String cachedToken = redisTemplate.opsForValue().get(REDIS_BAIDU_KEY);
if (cachedToken != null) {
return cachedToken;
}
// 2. Redis中没有加锁防止并发请求刷新Token
synchronized (this) {
// 再次检查,避免其他线程已经刷新
cachedToken = redisTemplate.opsForValue().get(REDIS_BAIDU_KEY);
if (cachedToken != null) {
return cachedToken;
}
// 3. 真正调用API获取新Token
String newToken = fetchAccessTokenFromBaidu();
if (newToken != null) {
// 4. 将新Token存入Redis并设置过期时间比实际有效期短一些
redisTemplate.opsForValue().set(REDIS_BAIDU_KEY, newToken, 29, TimeUnit.DAYS);
return newToken;
}
}
return null; // 获取失败
}
/**
* 从百度API获取AccessToken
*/
private String fetchAccessTokenFromBaidu() {
String url = String.format(TOKEN_URL, clientId, clientSecret);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.noBody())
.build();
try {
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
AccessTokenResponse tokenResponse = gson.fromJson(response.body(), AccessTokenResponse.class);
return tokenResponse.getAccessToken();
} else {
throw new IOException("获取AccessToken失败状态码: " + response.statusCode());
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("调用百度API获取AccessToken失败", e);
}
}
}

View File

@ -0,0 +1,205 @@
package org.dromara.common.utils.baiduUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dromara.common.utils.baiduUtil.entity.face.ComparisonRes;
import org.dromara.common.utils.baiduUtil.entity.face.HumanFaceReq;
import org.dromara.common.utils.baiduUtil.entity.face.HumanFaceRes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @Author 铁憨憨
* @Date 2025/7/18 17:09
* @Version 1.0
* 处理百度人脸相关逻辑:人脸检测、人脸对比
*/
@Service
public class BaiDuFace {
@Autowired
private BaiDuCommon baiDuCommon;
@Autowired
private HttpClient httpClient;
@Autowired
private ObjectMapper objectMapper;
// 人脸识别API地址
private static final String FACE_DETECT_URL = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=%s";
// 人脸对比API地址
private static final String FACE_COMPARE_URL = "https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=%s";
/**
* 人脸识别+人脸检测
* @param request 人脸请求参数
* @throws RuntimeException 检测失败时抛出异常由Spring统一处理
*/
public void humanFace(HumanFaceReq request) {
// 1. 获取AccessToken
String accessToken = baiDuCommon.getAccessToken();
if (accessToken == null || accessToken.trim().isEmpty()) {
throw new RuntimeException("获取访问令牌失败token为空");
}
// 2. 构建请求URL
String requestUrl = String.format(FACE_DETECT_URL, URLEncoder.encode(accessToken, StandardCharsets.UTF_8));
try {
// 3. 序列化请求参数
String requestBody = objectMapper.writeValueAsString(request);
// 4. 构建HTTP请求
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(requestUrl))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
// 5. 发送请求并获取响应
HttpResponse<String> response = httpClient.send(
httpRequest,
HttpResponse.BodyHandlers.ofString()
);
// 6. 解析响应结果
HumanFaceRes faceRep = objectMapper.readValue(response.body(), HumanFaceRes.class);
// 7. 处理API返回错误
if (faceRep.getErrorCode() != 0) {
throw new RuntimeException("错误码说明:" + faceRep.getErrorMsg());
}
// 8. 验证人脸信息(无人脸时抛出异常)
if (faceRep.getResult() == null
|| faceRep.getResult().getFaceList() == null
|| faceRep.getResult().getFaceList().isEmpty()) {
throw new RuntimeException("未检测到有效人脸信息");
}
// 9. 人脸质量校验
HumanFaceRes.FaceList faceInfo = faceRep.getResult().getFaceList().get(0);
// 9.1 人脸置信度校验必须为1.0
if (faceInfo.getFaceProbability() != 1.0) {
throw new RuntimeException("人脸置信度过低,请重新拍摄!");
}
// 9.2 真实人脸校验(排除卡通人脸)
HumanFaceRes.FaceType faceType = faceInfo.getFaceType();
if (faceType == null) {
throw new RuntimeException("无法判断人脸类型");
}
if ("cartoon".equals(faceType.getType())) {
throw new RuntimeException("请传入真实人脸,勿使用卡通图像");
}
// 校验真实人脸置信度需≥0.8
if (faceType.getProbability() < 0.8) {
throw new RuntimeException("人脸识别不清晰,请换个角度拍摄");
}
// 9.3 人脸模糊度校验模糊度≥0.1视为模糊)
HumanFaceRes.Quality quality = faceInfo.getQuality();
if (quality == null) {
throw new RuntimeException("无法获取人脸质量信息");
}
if (quality.getBlur() != 0) {
throw new RuntimeException("人脸过于模糊,请保持镜头稳定");
}
// 9.4 光线校验(光线值<100视为过暗
if (quality.getIllumination() < 100.0) {
throw new RuntimeException("光线太暗,请在光线充足的环境下拍摄");
}
// 9.5 人脸完整性校验1为完整0为不完整
if (quality.getCompleteness() != 1) {
throw new RuntimeException("人脸未完全显示,请确保面部在框内");
}
} catch (JsonProcessingException e) {
throw new RuntimeException("请求参数序列化失败:" + e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException("IO处理异常" + e.getMessage(), e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
throw new RuntimeException("请求被中断:" + e.getMessage(), e);
}
}
/**
* 人脸对比(计算人脸相似度)
* @param requestList 人脸请求参数列表至少包含2个人脸
* @return 人脸相似度得分
* @throws RuntimeException 对比失败时抛出异常
*/
public double comparison(List<HumanFaceReq> requestList) {
// 1. 校验请求参数
if (requestList == null || requestList.size() < 2) {
throw new RuntimeException("人脸对比至少需要2张人脸图片");
}
// 2. 获取AccessToken
String accessToken = baiDuCommon.getAccessToken();
if (accessToken == null || accessToken.trim().isEmpty()) {
throw new RuntimeException("获取访问令牌失败token为空");
}
// 3. 构建请求URL
String requestUrl = String.format(FACE_COMPARE_URL, URLEncoder.encode(accessToken, StandardCharsets.UTF_8));
try {
// 4. 序列化请求参数
String requestBody = objectMapper.writeValueAsString(requestList);
// 5. 构建HTTP请求
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(requestUrl))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
// 6. 发送请求并获取响应
HttpResponse<String> response = httpClient.send(
httpRequest,
HttpResponse.BodyHandlers.ofString()
);
// 7. 解析响应结果
ComparisonRes comparisonRep = objectMapper.readValue(response.body(), ComparisonRes.class);
// 8. 处理API返回错误
if (comparisonRep.getErrorCode() != 0) {
throw new RuntimeException("人脸对比失败:" + comparisonRep.getErrorMsg()
+ "(错误码:" + comparisonRep.getErrorCode() + "");
}
// 9. 校验对比结果
if (comparisonRep.getResult() == null) {
throw new RuntimeException("人脸对比结果为空");
}
return comparisonRep.getResult().getScore();
} catch (JsonProcessingException e) {
throw new RuntimeException("请求参数序列化失败:" + e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException("IO处理异常" + e.getMessage(), e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("请求被中断:" + e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,204 @@
package org.dromara.common.utils.baiduUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dromara.common.utils.baiduUtil.entity.ocr.IDCardInfo;
import org.dromara.common.utils.baiduUtil.entity.ocr.OcrReq;
import org.dromara.common.utils.baiduUtil.entity.ocr.Result;
import org.dromara.common.utils.baiduUtil.entity.ocr.WordsResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:45
* @Version 1.0
*
* 处理百度OCR相关逻辑身份证识别、银行卡识别
*/
@Service
public class BaiDuOCR {
@Autowired
private BaiDuCommon baiDuCommon;
@Autowired
private HttpClient httpClient;
@Autowired
private ObjectMapper objectMapper; //ObjectMapper 是 Java 处理 JSON 的核心工具,项目中使用它进行 JSON 与 Java 对象的相互转换。
String baseUrlTemplate = "https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard?access_token=%s";
String BASE_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=%s";
/**
* @description 银行卡OCR识别
* @author 铁憨憨
* @date 2025/7/18 11:50
* @param vr 请求参数
* @return 识别结果Result
**/
public Result bankCardOCRRecognition(OcrReq vr) {
// 先从缓存里面捞取token若为空直接抛出异常
String atStr = baiDuCommon.getAccessToken();
if (atStr == null || atStr.trim().isEmpty()) {
throw new RuntimeException("获取访问令牌失败token为空");
}
try {
// 构建请求URL包含token参数
String requestUrl = String.format(baseUrlTemplate, URLEncoder.encode(atStr, StandardCharsets.UTF_8));
// 准备请求体将请求参数转为JSON
String requestBody = objectMapper.writeValueAsString(vr);
if (requestBody == null) {
throw new RuntimeException("请求参数序列化失败");
}
// 构建HTTP请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(requestUrl))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
// 发送请求并获取响应
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// 处理响应状态码非200直接抛出异常
if (response.statusCode() != 200) {
throw new RuntimeException("接口请求失败,状态码:" + response.statusCode() + ",响应信息:" + response.body());
}
// 解析响应结果(若解析失败抛出异常)
Result result = objectMapper.readValue(response.body(), Result.class);
if (result == null) {
throw new RuntimeException("响应结果解析失败");
}
// // 若接口返回错误码如百度API的error_code抛出异常
// if (result.getErrorCode() != null && result.getErrorCode() != 0) {
// throw new RuntimeException("接口返回错误:" + result.getErrorMessage() + "(错误码:" + result.getErrorCode() + "");
// }
return result;
} catch (IOException e) {
// IO异常如序列化失败、网络IO错误
throw new RuntimeException("IO处理异常" + e.getMessage(), e);
} catch (InterruptedException e) {
// 线程中断异常
Thread.currentThread().interrupt(); // 恢复中断状态
throw new RuntimeException("请求被中断:" + e.getMessage(), e);
}
}
/**
* @description 身份证OCR识别
* @author 铁憨憨
* @date 2025/7/18 16:53
* @param request 请求参数
* @return 识别结果WordsResult
**/
public WordsResult idCardOCR(OcrReq request) {
// 获取AccessToken为空直接抛异常
String accessToken = baiDuCommon.getAccessToken();
if (accessToken == null || accessToken.trim().isEmpty()) {
throw new RuntimeException("获取访问令牌失败token为空");
}
// 构建请求URL
String requestUrl = String.format(BASE_URL, accessToken);
try {
// 准备请求体(序列化失败抛异常)
String requestBody = objectMapper.writeValueAsString(request);
if (requestBody == null) {
throw new RuntimeException("请求参数序列化失败");
}
// 构建HTTP请求
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(requestUrl))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
// 发送请求并获取响应
HttpResponse<String> response = httpClient.send(
httpRequest,
HttpResponse.BodyHandlers.ofString()
);
// 处理响应状态码非200直接抛异常
if (response.statusCode() != 200) {
throw new RuntimeException("接口请求失败,状态码:" + response.statusCode() + ",响应信息:" + response.body());
}
// 处理响应内容(去除空格并解析)
String responseBody = response.body().replaceAll("\\s+", "");
IDCardInfo idCardInfo = objectMapper.readValue(responseBody, IDCardInfo.class);
if (idCardInfo == null) {
throw new RuntimeException("响应结果解析失败");
}
// 检查身份证状态状态异常由validateImageStatus抛异常
validateImageStatus(idCardInfo.getImageStatus());
// 提取识别结果(结果为空抛异常)
WordsResult wordsResult = idCardInfo.getWordsResult();
if (wordsResult == null) {
throw new RuntimeException("未识别到身份证信息");
}
return wordsResult;
} catch (IOException e) {
// IO异常序列化、网络IO等
throw new RuntimeException("IO处理异常" + e.getMessage(), e);
} catch (InterruptedException e) {
// 线程中断异常
Thread.currentThread().interrupt(); // 恢复中断状态
throw new RuntimeException("请求被中断:" + e.getMessage(), e);
}
}
/**
* @description 验证身份证图片状态
* @author 铁憨憨
* @date 2025/7/18 17:08
* @param imageStatus 图片状态
* @throws RuntimeException 当状态不正常时抛出运行时异常
**/
private void validateImageStatus(String imageStatus) {
if (imageStatus == null || "normal".equals(imageStatus)) {
return; // 正常状态,直接返回
}
// 根据不同状态码抛出不同的异常信息
String errorMessage = switch (imageStatus) {
case "reversed_side" -> "身份证正反面颠倒,请调整后重新上传";
case "non_idcard" -> "上传的图片中不包含身份证,请重新上传";
case "blurred" -> "身份证图片模糊,请重新上传清晰的图片";
case "other_type_card" -> "上传的不是身份证,请上传有效的身份证图片";
case "over_exposure" -> "身份证关键字段反光或过曝,请调整光线后重新上传";
case "over_dark" -> "身份证图片欠曝(亮度过低),请调整光线后重新上传";
default -> "未知错误:" + imageStatus;
};
throw new RuntimeException(errorMessage);
}
}

View File

@ -0,0 +1,19 @@
package org.dromara.common.utils.baiduUtil.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @Author 铁憨憨
* @Date 2025/7/18 9:56
* @Version 1.0
*/
@Data
@Accessors(chain = true)
public class AccessTokenResponse {
private String accessToken;
private int expiresIn;
private String scope;
}

View File

@ -0,0 +1,49 @@
package org.dromara.common.utils.baiduUtil.entity.face;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* @Author 铁憨憨
* @Date 2025/7/18 17:15
* @Version 1.0
*
* 人脸对比响应结果
*/
@Data
public class ComparisonRes {
@JsonProperty("error_code")
private int errorCode;
@JsonProperty("error_msg")
private String errorMsg;
@JsonProperty("log_id")
private long logId;
@JsonProperty("timestamp")
private long timestamp;
@JsonProperty("cached")
private int cached;
@JsonProperty("result")
private CompareResult result;
@Data
public static class CompareResult {
@JsonProperty("score")
private double score; // 人脸相似度得分
@JsonProperty("face_list")
private List<FaceToken> faceList;
}
@Data
public static class FaceToken {
@JsonProperty("face_token")
private String faceToken;
}
}

View File

@ -0,0 +1,23 @@
package org.dromara.common.utils.baiduUtil.entity.face;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 17:12
* @Version 1.0
*
* 人脸识别请求参数
*/
@Data
public class HumanFaceReq {
@JsonProperty("image")
private String image; // 图片base64字符串
@JsonProperty("image_type")
private String imageType = "BASE64"; // 图片类型固定为BASE64
@JsonProperty("face_field")
private String faceField = "face_type,quality"; // 需要返回的人脸字段
}

View File

@ -0,0 +1,142 @@
package org.dromara.common.utils.baiduUtil.entity.face;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* @Author 铁憨憨
* @Date 2025/7/18 17:13
* @Version 1.0
*
* 人脸识别响应结果
*/
@Data
public class HumanFaceRes {
@JsonProperty("error_code")
private int errorCode;
@JsonProperty("error_msg")
private String errorMsg;
@JsonProperty("log_id")
private long logId;
@JsonProperty("timestamp")
private long timestamp;
@JsonProperty("cached")
private int cached;
@JsonProperty("result")
private Result result;
@Data
public static class Result {
@JsonProperty("face_num")
private int faceNum;
@JsonProperty("face_list")
private List<FaceList> faceList;
}
@Data
public static class FaceList {
@JsonProperty("face_token")
private String faceToken;
@JsonProperty("location")
private Location location;
@JsonProperty("face_probability")
private double faceProbability;
@JsonProperty("angle")
private Angle angle;
@JsonProperty("face_type")
private FaceType faceType;
@JsonProperty("quality")
private Quality quality;
}
@Data
public static class Location {
@JsonProperty("left")
private double left;
@JsonProperty("top")
private double top;
@JsonProperty("width")
private int width;
@JsonProperty("height")
private int height;
@JsonProperty("rotation")
private int rotation;
}
@Data
public static class Angle {
@JsonProperty("yaw")
private double yaw;
@JsonProperty("pitch")
private double pitch;
@JsonProperty("roll")
private double roll;
}
@Data
public static class FaceType {
@JsonProperty("type")
private String type;
@JsonProperty("probability")
private double probability;
}
@Data
public static class Quality {
@JsonProperty("occlusion")
private Occlusion occlusion;
@JsonProperty("blur")
private double blur;
@JsonProperty("illumination")
private double illumination;
@JsonProperty("completeness")
private long completeness;
}
@Data
public static class Occlusion {
@JsonProperty("left_eye")
private double leftEye;
@JsonProperty("right_eye")
private double rightEye;
@JsonProperty("nose")
private double nose;
@JsonProperty("mouth")
private double mouth;
@JsonProperty("left_cheek")
private double leftCheek;
@JsonProperty("right_cheek")
private double rightCheek;
@JsonProperty("chin_contour")
private double chinContour;
}
}

View File

@ -0,0 +1,39 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:58
* @Version 1.0
*
* 银行卡具体信息
*/
@Data
//public class BankData {
// private String valid_date; // 有效期
// private String bank_card_number; // 卡号
// private String bank_name; // 银行名称
// private int bank_card_type; // 卡类型0未知1借记卡2贷记卡等
// private String holder_name; // 持卡人姓名(可能为空)
//}
public class BankData {
@JSONField(name = "bank_card_number",label = "银行卡卡号")
private String bankCardNumber;
@JSONField(name = "valid_date",label = "有效期")
private String validDate;
@JSONField(name = "bank_card_type",label = "银行卡类型0不能识别; 1借记卡; 2贷记卡原信用卡大部分为贷记卡; 3准贷记卡; 4预付费卡")
private int bankCardType;
@JSONField(name = "bank_name",label = "银行名,不能识别时为空")
private String bankName;
@JSONField(name = "holder_name",label = "持卡人姓名,不能识别时为空")
private String holderName;
}

View File

@ -0,0 +1,16 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:55
* @Version 1.0
*
* 单个识别字段(含文字和位置)
*/
@Data
public class Field {
private Location location; // 位置信息
private String words; // 识别文字
}

View File

@ -0,0 +1,30 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:50
* @Version 1.0
*
* 身份证识别结果
*/
@Data
public class IDCardInfo {
@JSONField(name = "words_result")
private WordsResult wordsResult; // 识别字段集合(姓名、身份证号等)
@JSONField(name = "words_result_num")
private int wordsResultNum; // 识别字段数量
@JSONField(name = "idcard_number_type")
private int idCardNumberType; // 身份证类型如18位/15位
private String imageStatus; // 图像状态(如是否颠倒)
@JSONField(name = "log_id")
private long logId; // 请求唯一标识日志ID
private String photo; // 身份证照片base64若检测
}

View File

@ -0,0 +1,18 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:56
* @Version 1.0
*
* 位置信息(坐标)
*/
@Data
public class Location {
private int top; // 顶部坐标
private int left; // 左侧坐标
private int width; // 宽度
private int height; // 高度
}

View File

@ -0,0 +1,24 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:47
* @Version 1.0
*
* OCR请求参数身份证/银行卡通用)
*/
@Data
public class OcrReq {
private String image; // 图像base64与url二选一
private String url; // 图像URL与image二选一
@JSONField(name = "id_card_side")
private String idCardSide; // 身份证正反面front/back银行卡无需
@JSONField(name = "detect_photo")
private boolean detectPhoto;// 是是否开启银行卡质量类型(清晰模糊、边框/四角不完整检测功能默认不开启false。
}

View File

@ -0,0 +1,22 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 11:20
* @Version 1.0
*
* 银行卡识别的完整返回结果
*/
@Data
public class Result {
@JSONField(name = "result")
private BankData res;
private int direction;
@JSONField(name = "log_id")
private long logId;
}

View File

@ -0,0 +1,33 @@
package org.dromara.common.utils.baiduUtil.entity.ocr;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* @Author 铁憨憨
* @Date 2025/7/18 10:50
* @Version 1.0
*
* 身份证识别字段集合
*/
@Data
public class WordsResult {
@JSONField(name = "姓名")
private Field name; // 姓名
@JSONField(name = "民族")
private Field nation; // 民族
@JSONField(name = "住址")
private Field address; // 住址
@JSONField(name = "公民身份号码")
private Field citizenIdentification; // 身份证号
@JSONField(name = "出生")
private Field birth; // 出生日期
@JSONField(name = "性别")
private Field gender; // 性别
@JSONField(name = "失效日期")
private Field expirationDate; // 失效日期
@JSONField(name = "签发机关")
private Field issuingAuthority; // 签发机关
@JSONField(name = "签发日期")
private Field issueDate; // 签发日期
}

View File

@ -0,0 +1,166 @@
package org.dromara.common.utils.documentOperations;
import jakarta.annotation.Resource;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.docx4j.Docx4J;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.dromara.system.domain.vo.SysOssUploadVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.dromara.common.constant.MinioPathConstant.ContactNotice;
@Component
public class WordToPdfToImg {
@Resource
private ISysOssService ossService;
/**
* wordToImg 根据file生成缩略图路径
*
* @param file 文件
*/
public String wordToImg(MultipartFile file) throws Docx4JException, IOException {
String mergedPath = "output/merged.png";
// ✅ 1. Word → PDF内存
ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
// 直接走路径
// WordprocessingMLPackage wordML = WordprocessingMLPackage.load(new File(docxPath));
// 直接走文件word不落地
WordprocessingMLPackage wordML = WordprocessingMLPackage.load(file.getInputStream());
Docx4J.toPDF(wordML, pdfOut);
// ✅ 2. PDF → 各页 PNG
List<BufferedImage> pages = new ArrayList<>();
try (PDDocument pdf = PDDocument.load(new ByteArrayInputStream(pdfOut.toByteArray()))) {
PDFRenderer renderer = new PDFRenderer(pdf);
for (int i = 0; i < pdf.getNumberOfPages(); i++) {
BufferedImage img = renderer.renderImageWithDPI(i, 144);
pages.add(img);
// ImageIO.write(img, "png", new File(outDir, "page_" + i + ".png"));
}
}
// ✅ 3. 合成所有页为一张长图
int totalHeight = pages.stream().mapToInt(BufferedImage::getHeight).sum();
int maxWidth = pages.stream().mapToInt(BufferedImage::getWidth).max().orElse(0);
BufferedImage merged = new BufferedImage(maxWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = merged.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, maxWidth, totalHeight);
int y = 0;
for (BufferedImage img : pages) {
g.drawImage(img, 0, y, null);
y += img.getHeight();
}
g.dispose();
ImageIO.write(merged, "png", new File(mergedPath));
System.out.println("✅ 成功合并图片:" + mergedPath);
return mergedPath;
}
/**
* convertWordToImage 根据MultipartFile转成缩略图 并上传至minio
*
* @param wordFile 文件
*/
public SysOssUploadVo convertWordToImage(MultipartFile wordFile) throws Exception {
// 1. Word -> PDF (内存)
WordprocessingMLPackage wordML = WordprocessingMLPackage.load(wordFile.getInputStream());
ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
Docx4J.toPDF(wordML, pdfOut);
// 2. PDF -> BufferedImage 每页
List<BufferedImage> pages = new ArrayList<>();
try (PDDocument document = PDDocument.load(new ByteArrayInputStream(pdfOut.toByteArray()))) {
PDFRenderer renderer = new PDFRenderer(document);
for (int i = 0; i < document.getNumberOfPages(); i++) {
BufferedImage img = renderer.renderImageWithDPI(i, 144);
pages.add(img);
}
}
// 3. 合并图片为一张长图
int width = pages.stream().mapToInt(BufferedImage::getWidth).max().orElse(0);
int totalHeight = pages.stream().mapToInt(BufferedImage::getHeight).sum();
BufferedImage merged = new BufferedImage(width, totalHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = merged.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, totalHeight);
int y = 0;
for (BufferedImage img : pages) {
g.drawImage(img, 0, y, null);
y += img.getHeight();
}
g.dispose();
// 4. 写入 ByteArrayOutputStream 并转换为 MultipartFile
ByteArrayOutputStream imageOut = new ByteArrayOutputStream();
ImageIO.write(merged, "png", imageOut);
MockMultipartFile image = new MockMultipartFile(
"image", // 字段名
wordFile.getOriginalFilename() + ".png", // 文件名
"image/png", // ContentType
new ByteArrayInputStream(imageOut.toByteArray()) // 文件内容
);
return ossService.uploadWithNoSave(image, ossService.minioFileName(ContactNotice, image));
}
// public static void main(String[] args) throws Exception {
// String docxPath = "C:\\Users\\YuanJie-DSJ\\Downloads\\123.docx";
// String outDir = "output/pages";
// String mergedPath = "output/merged.png";
//
// new File(outDir).mkdirs();
//
// // ✅ 1. Word → PDF内存
// ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
// WordprocessingMLPackage wordML = WordprocessingMLPackage.load(new File(docxPath));
// Docx4J.toPDF(wordML, pdfOut); // 推荐 facade 方法 :contentReference[oaicite:2]{index=2}
// // ✅ 2. PDF → 各页 PNG
// List<BufferedImage> pages = new ArrayList<>();
// try (PDDocument pdf = PDDocument.load(new ByteArrayInputStream(pdfOut.toByteArray()))) {
// PDFRenderer renderer = new PDFRenderer(pdf);
// for (int i = 0; i < pdf.getNumberOfPages(); i++) {
// BufferedImage img = renderer.renderImageWithDPI(i, 144);
// pages.add(img);
//// ImageIO.write(img, "png", new File(outDir, "page_" + i + ".png"));
// }
// }
// // ✅ 3. 合成所有页为一张长图
// int totalHeight = pages.stream().mapToInt(BufferedImage::getHeight).sum();
// int maxWidth = pages.stream().mapToInt(BufferedImage::getWidth).max().orElse(0);
// BufferedImage merged = new BufferedImage(maxWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
// Graphics2D g = merged.createGraphics();
// g.setColor(Color.WHITE);
// g.fillRect(0, 0, maxWidth, totalHeight);
//
// int y = 0;
// for (BufferedImage img : pages) {
// g.drawImage(img, 0, y, null);
// y += img.getHeight();
// }
// g.dispose();
//
// ImageIO.write(merged, "png", new File(mergedPath));
// System.out.println("✅ 成功合并图片:" + mergedPath);
// }
}

View File

@ -0,0 +1,21 @@
package org.dromara.contractor.config;
import jakarta.annotation.Resource;
import org.dromara.contractor.interceptor.ContractorInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private ContractorInterceptor contractorInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(contractorInterceptor)
.addPathPatterns("/contractor/**") // 拦截所有 /contractor 开头
.excludePathPatterns("/contractor/contractor/**"); // 排除具体路径
}
}

View File

@ -0,0 +1,14 @@
package org.dromara.contractor.constant;
/**
* @author lilemy
* @date 2025/4/2 17:18
*/
public interface SubConstructionUserConstant {
/**
* 施工人员文件类型字典
*/
String USER_FILE_TYPE = "user_file_type";
}

View File

@ -0,0 +1,193 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.constructionuser.*;
import org.dromara.contractor.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserAttendanceMonthVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserAttendanceTotalVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserGisVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 施工人员
*
* @author lilemy
* @date 2025-03-07
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/contractor/constructionUser")
public class SubConstructionUserController extends BaseController {
private final ISubConstructionUserService constructionUserService;
/**
* 查询施工人员列表
*/
@SaCheckPermission("contractor:constructionUser:list")
@GetMapping("/list")
public TableDataInfo<SubConstructionUserVo> list(SubConstructionUserQueryReq req, PageQuery pageQuery) {
return constructionUserService.queryPageList(req, pageQuery);
}
/**
* 查询每个施工人员总的考勤列表
*/
@SaCheckPermission(value = {"contractor:constructionUser:list", "project:attendance:list"})
@GetMapping("/list/attendance/total")
public TableDataInfo<SubConstructionUserAttendanceTotalVo> listAttendanceTotal(SubConstructionUserAttendanceQueryReq req,
PageQuery pageQuery) {
return constructionUserService.queryPageAttendanceList(req, pageQuery);
}
/**
* 查询施工人员月份考勤列表
*/
@SaCheckPermission("contractor:constructionUser:list")
@GetMapping("/list/attendance/month")
public R<List<SubConstructionUserAttendanceMonthVo>> listAttendanceMonth(SubConstructionUserAttendanceMonthReq req) {
return R.ok(constructionUserService.queryAttendanceMonthList(req));
}
/**
* 导出施工人员列表
*/
@SaCheckPermission("contractor:constructionUser:export")
@Log(title = "施工人员", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubConstructionUserQueryReq req, HttpServletResponse response) {
List<BusConstructionUserExportVo> list = constructionUserService.queryList(req);
ExcelUtil.exportExcel(list, "施工人员", BusConstructionUserExportVo.class, response);
}
/**
* 获取施工人员详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:constructionUser:query")
@GetMapping("/{id}")
public R<SubConstructionUserVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(constructionUserService.queryById(id));
}
/**
* 查询大屏施工人员信息
*/
@SaCheckPermission("contractor:constructionUser:query")
@GetMapping("/gis")
public R<SubConstructionUserGisVo> getGisData(SubConstructionUserGisReq req) {
return R.ok(constructionUserService.getGisData(req));
}
/**
* 新增施工人员
*/
@SaCheckPermission("contractor:constructionUser:add")
@Log(title = "施工人员", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody SubConstructionUserCreateReq req) {
return R.ok(constructionUserService.insertByBo(req));
}
/**
* 修改施工人员
*/
@SaCheckPermission("contractor:constructionUser:edit")
@Log(title = "施工人员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SubConstructionUserUpdateReq req) {
return toAjax(constructionUserService.updateByBo(req));
}
/**
* 修改施工人员工资
*/
@SaCheckPermission("contractor:constructionUser:edit")
@Log(title = "施工人员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/salary")
public R<Void> editSalary(@Validated(EditGroup.class) @RequestBody SubConstructionUserUpdateSalaryReq req) {
return toAjax(constructionUserService.updateSalary(req));
}
/**
* 修改施工人员打卡状态
*/
@SaCheckPermission("contractor:constructionUser:edit")
@Log(title = "施工人员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/clock")
public R<Void> editClock(@Validated(EditGroup.class) @RequestBody SubConstructionUserUpdateClockReq req) {
return toAjax(constructionUserService.updateClock(req));
}
/**
* 批量修改施工人员状态
*/
@SaCheckPermission("contractor:constructionUser:edit")
@Log(title = "施工人员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/batch/status")
public R<Void> batchUpdateStatus(@Validated(EditGroup.class) @RequestBody SubConstructionUserBatchUpdateStatusReq req) {
return toAjax(constructionUserService.batchUpdateStatus(req));
}
/**
* 根据项目id批量修改施工人员打卡状态
*/
@SaCheckPermission("contractor:constructionUser:edit")
@Log(title = "施工人员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/batch/clock")
public R<Void> batchUpdateClock(@Validated(EditGroup.class) @RequestBody SubConstructionUserBatchUpdateClockReq req) {
return toAjax(constructionUserService.batchUpdateClockByProjectId(req));
}
/**
* 施工人员迁移
*/
@SaCheckPermission("contractor:constructionUser:migration")
@Log(title = "施工人员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/change/project")
public R<Void> changeUserProject(@Validated(EditGroup.class) @RequestBody SubConstructionUserChangeProjectReq req) {
return toAjax(constructionUserService.changeUserProject(req));
}
/**
* 删除施工人员
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:constructionUser:remove")
@Log(title = "施工人员", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(constructionUserService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,104 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.constructionuserfile.SubConstructionUserFileQueryReq;
import org.dromara.contractor.domain.dto.constructionuserfile.SubConstructionUserFileSaveReq;
import org.dromara.contractor.domain.dto.constructionuserfile.SubConstructionUserFileTemplateReq;
import org.dromara.contractor.domain.vo.constructionuserfile.SubConstructionUserFileVo;
import org.dromara.contractor.service.ISubConstructionUserFileService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 施工人员文件存储
*
* @author lilemy
* @date 2025-04-01
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/contractor/constructionUserFile")
public class SubConstructionUserFileController extends BaseController {
private final ISubConstructionUserFileService constructionUserFileService;
/**
* 查询施工人员文件存储列表
*/
@SaCheckPermission(value = {"project:constructionUserFile:list", "contractor:constructionUserFile:list"}, mode = SaMode.OR)
@GetMapping("/list")
public R<List<SubConstructionUserFileVo>> list(SubConstructionUserFileQueryReq req) {
return R.ok(constructionUserFileService.queryList(req));
}
/**
* 导出施工人员文件存储列表
*/
@SaCheckPermission(value = {"project:constructionUserFile:export", "contractor:constructionUserFile:export"}, mode = SaMode.OR)
@Log(title = "施工人员文件存储", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubConstructionUserFileQueryReq req, HttpServletResponse response) {
List<SubConstructionUserFileVo> list = constructionUserFileService.queryList(req);
ExcelUtil.exportExcel(list, "施工人员文件存储", SubConstructionUserFileVo.class, response);
}
/**
* 下载施工人员文件存储模板
*/
@SaCheckPermission(value = {"project:constructionUserFile:download", "contractor:constructionUserFile:download"}, mode = SaMode.OR)
@Log(title = "施工人员文件存储", businessType = BusinessType.EXPORT)
@RepeatSubmit()
@PostMapping("/exportFileTemplate")
public void exportFileTemplate(SubConstructionUserFileTemplateReq req, HttpServletResponse response) {
constructionUserFileService.downloadFileTemplate(req, response);
}
/**
* 上传施工人员文件压缩包,批量导入存储施工人员文件
*/
@SaCheckPermission(value = {"project:constructionUserFile:upload", "contractor:constructionUserFile:upload"}, mode = SaMode.OR)
@Log(title = "施工人员文件存储", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/upload/zip")
public R<Boolean> uploadFileZip(@RequestParam("file") MultipartFile file) {
Boolean result = constructionUserFileService.batchUploadFileByZip(file);
return R.ok(result);
}
/**
* 获取施工人员文件存储详细信息
*
* @param id 主键
*/
@SaCheckPermission(value = {"project:constructionUserFile:query", "contractor:constructionUserFile:query"}, mode = SaMode.OR)
@GetMapping("/{id}")
public R<SubConstructionUserFileVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(constructionUserFileService.queryById(id));
}
/**
* 保存施工人员文件存储详情信息
*/
@SaCheckPermission(value = {"project:constructionUserFile:save", "contractor:constructionUserFile:save"}, mode = SaMode.OR)
@Log(title = "施工人员文件存储", businessType = BusinessType.INSERT)
@PostMapping("/save")
public R<Boolean> save(@RequestBody SubConstructionUserFileSaveReq req) {
return R.ok(constructionUserFileService.saveFileList(req));
}
}

View File

@ -0,0 +1,118 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.contractor.SubContractorCreateReq;
import org.dromara.contractor.domain.dto.contractor.SubContractorQueryReq;
import org.dromara.contractor.domain.dto.contractor.SubContractorUpdateReq;
import org.dromara.contractor.domain.vo.contractor.SubContractorVo;
import org.dromara.contractor.service.ISubContractorService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包单位
*
* @author lilemy
* @date 2025-03-07
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/contractor/contractor")
public class SubContractorController extends BaseController {
private final ISubContractorService contractorService;
/**
* 查询分包单位列表
*/
@SaCheckPermission("contractor:contractor:list")
@GetMapping("/list")
public TableDataInfo<SubContractorVo> list(SubContractorQueryReq req, PageQuery pageQuery) {
return contractorService.queryPageList(req, pageQuery);
}
/**
* 查询没有绑定部门的分包单位列表
*/
@SaCheckPermission("contractor:contractor:listNoDept")
@GetMapping("/listNoDept/{projectId}")
public List<SubContractorVo> listNoDept(@NotNull(message = "项目主键不能为空")
@PathVariable Long projectId) {
return contractorService.queryListNoDept(projectId);
}
/**
* 导出分包单位列表
*/
@SaCheckPermission("contractor:contractor:export")
@Log(title = "分包单位", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubContractorQueryReq req, HttpServletResponse response) {
List<SubContractorVo> list = contractorService.queryList(req);
ExcelUtil.exportExcel(list, "分包单位", SubContractorVo.class, response);
}
/**
* 获取分包单位详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:contractor:query")
@GetMapping("/{id}")
public R<SubContractorVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(contractorService.queryById(id));
}
/**
* 新增分包单位
*/
@SaCheckPermission("contractor:contractor:add")
@Log(title = "分包单位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody SubContractorCreateReq req) {
return R.ok(contractorService.insertByBo(req));
}
/**
* 修改分包单位
*/
@SaCheckPermission("contractor:contractor:edit")
@Log(title = "分包单位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SubContractorUpdateReq req) {
return toAjax(contractorService.updateByBo(req));
}
/**
* 删除分包单位
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:contractor:remove")
@Log(title = "分包单位", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(contractorService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,108 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.contractormaterial.SubContractorMaterialCreateReq;
import org.dromara.contractor.domain.dto.contractormaterial.SubContractorMaterialQueryReq;
import org.dromara.contractor.domain.dto.contractormaterial.SubContractorMaterialUpdateReq;
import org.dromara.contractor.domain.vo.contractormaterial.SubContractorMaterialVo;
import org.dromara.contractor.service.ISubContractorMaterialService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包方物料
*
* @author lilemy
* @date 2025-06-27
*/
@Validated
@RestController
@RequestMapping("/contractor/contractorMaterial")
public class SubContractorMaterialController extends BaseController {
@Resource
private ISubContractorMaterialService contractorMaterialService;
/**
* 查询分包方物料列表
*/
@SaCheckPermission("contractor:contractorMaterial:list")
@GetMapping("/list")
public TableDataInfo<SubContractorMaterialVo> list(SubContractorMaterialQueryReq req, PageQuery pageQuery) {
return contractorMaterialService.queryPageList(req, pageQuery);
}
/**
* 导出分包方物料列表
*/
@SaCheckPermission("contractor:contractorMaterial:export")
@Log(title = "分包方物料", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubContractorMaterialQueryReq req, HttpServletResponse response) {
List<SubContractorMaterialVo> list = contractorMaterialService.queryList(req);
ExcelUtil.exportExcel(list, "分包方物料", SubContractorMaterialVo.class, response);
}
/**
* 获取分包方物料详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:contractorMaterial:query")
@GetMapping("/{id}")
public R<SubContractorMaterialVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(contractorMaterialService.queryById(id));
}
/**
* 新增分包方物料
*/
@SaCheckPermission("contractor:contractorMaterial:add")
@Log(title = "分包方物料", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody SubContractorMaterialCreateReq req) {
return R.ok(contractorMaterialService.insertByBo(req));
}
/**
* 修改分包方物料
*/
@SaCheckPermission("contractor:contractorMaterial:edit")
@Log(title = "分包方物料", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SubContractorMaterialUpdateReq req) {
return toAjax(contractorMaterialService.updateByBo(req));
}
/**
* 删除分包方物料
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:contractorMaterial:remove")
@Log(title = "分包方物料", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(contractorMaterialService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,108 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.contractormaterialrecord.SubContractorMaterialRecordCreateReq;
import org.dromara.contractor.domain.dto.contractormaterialrecord.SubContractorMaterialRecordQueryReq;
import org.dromara.contractor.domain.dto.contractormaterialrecord.SubContractorMaterialRecordUpdateReq;
import org.dromara.contractor.domain.vo.contractormaterialrecord.SubContractorMaterialRecordVo;
import org.dromara.contractor.service.ISubContractorMaterialRecordService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包方物料记录
*
* @author lilemy
* @date 2025-06-27
*/
@Validated
@RestController
@RequestMapping("/contractor/contractorMaterialRecord")
public class SubContractorMaterialRecordController extends BaseController {
@Resource
private ISubContractorMaterialRecordService subContractorMaterialRecordService;
/**
* 查询分包方物料记录列表
*/
@SaCheckPermission("contractor:contractorMaterialRecord:list")
@GetMapping("/list")
public TableDataInfo<SubContractorMaterialRecordVo> list(SubContractorMaterialRecordQueryReq req, PageQuery pageQuery) {
return subContractorMaterialRecordService.queryPageList(req, pageQuery);
}
/**
* 导出分包方物料记录列表
*/
@SaCheckPermission("contractor:contractorMaterialRecord:export")
@Log(title = "分包方物料记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubContractorMaterialRecordQueryReq req, HttpServletResponse response) {
List<SubContractorMaterialRecordVo> list = subContractorMaterialRecordService.queryList(req);
ExcelUtil.exportExcel(list, "分包方物料记录", SubContractorMaterialRecordVo.class, response);
}
/**
* 获取分包方物料记录详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:contractorMaterialRecord:query")
@GetMapping("/{id}")
public R<SubContractorMaterialRecordVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(subContractorMaterialRecordService.queryById(id));
}
/**
* 新增分包方物料记录
*/
@SaCheckPermission("contractor:contractorMaterialRecord:add")
@Log(title = "分包方物料记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody SubContractorMaterialRecordCreateReq req) {
return R.ok(subContractorMaterialRecordService.insertByBo(req));
}
/**
* 修改分包方物料记录
*/
@SaCheckPermission("contractor:contractorMaterialRecord:edit")
@Log(title = "分包方物料记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SubContractorMaterialRecordUpdateReq req) {
return toAjax(subContractorMaterialRecordService.updateByBo(req));
}
/**
* 删除分包方物料记录
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:contractorMaterialRecord:remove")
@Log(title = "分包方物料记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(subContractorMaterialRecordService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,108 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.contractortool.SubContractorToolCreateReq;
import org.dromara.contractor.domain.dto.contractortool.SubContractorToolQueryReq;
import org.dromara.contractor.domain.dto.contractortool.SubContractorToolUpdateReq;
import org.dromara.contractor.domain.vo.contractortool.SubContractorToolVo;
import org.dromara.contractor.service.ISubContractorToolService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包方工器具
*
* @author lilemy
* @date 2025-06-26
*/
@Validated
@RestController
@RequestMapping("/contractor/contractorTool")
public class SubContractorToolController extends BaseController {
@Resource
private ISubContractorToolService busContractorToolService;
/**
* 查询分包方工器具列表
*/
@SaCheckPermission("contractor:contractorTool:list")
@GetMapping("/list")
public TableDataInfo<SubContractorToolVo> list(SubContractorToolQueryReq req, PageQuery pageQuery) {
return busContractorToolService.queryPageList(req, pageQuery);
}
/**
* 导出分包方工器具列表
*/
@SaCheckPermission("contractor:contractorTool:export")
@Log(title = "分包方工器具", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubContractorToolQueryReq req, HttpServletResponse response) {
List<SubContractorToolVo> list = busContractorToolService.queryList(req);
ExcelUtil.exportExcel(list, "分包方工器具", SubContractorToolVo.class, response);
}
/**
* 获取分包方工器具详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:contractorTool:query")
@GetMapping("/{id}")
public R<SubContractorToolVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(busContractorToolService.queryById(id));
}
/**
* 新增分包方工器具
*/
@SaCheckPermission("contractor:contractorTool:add")
@Log(title = "分包方工器具", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody SubContractorToolCreateReq req) {
return R.ok(busContractorToolService.insertByBo(req));
}
/**
* 修改分包方工器具
*/
@SaCheckPermission("contractor:contractorTool:edit")
@Log(title = "分包方工器具", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SubContractorToolUpdateReq req) {
return toAjax(busContractorToolService.updateByBo(req));
}
/**
* 删除分包方工器具
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:contractorTool:remove")
@Log(title = "分包方工器具", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(busContractorToolService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,106 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.contractortoolentry.SubContractorToolRecordCreateReq;
import org.dromara.contractor.domain.dto.contractortoolentry.SubContractorToolRecordQueryReq;
import org.dromara.contractor.domain.dto.contractortoolentry.SubContractorToolRecordUpdateReq;
import org.dromara.contractor.domain.vo.contractortoolentry.SubContractorToolRecordVo;
import org.dromara.contractor.service.ISubContractorToolRecordService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包方工器具记录
*
* @author lilemy
* @date 2025-06-26
*/
@Validated
@RestController
@RequestMapping("/contractor/contractorToolRecord")
public class SubContractorToolRecordController extends BaseController {
@Resource
private ISubContractorToolRecordService contractorToolRecordService;
/**
* 查询分包方工器具记录列表
*/
@SaCheckPermission("contractor:contractorToolRecord:list")
@GetMapping("/list")
public TableDataInfo<SubContractorToolRecordVo> list(SubContractorToolRecordQueryReq req, PageQuery pageQuery) {
return contractorToolRecordService.queryPageList(req, pageQuery);
}
/**
* 导出分包方工器具记录列表
*/
@SaCheckPermission("contractor:contractorToolRecord:export")
@Log(title = "分包方工器具记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(SubContractorToolRecordQueryReq req, HttpServletResponse response) {
List<SubContractorToolRecordVo> list = contractorToolRecordService.queryList(req);
ExcelUtil.exportExcel(list, "分包方工器具记录", SubContractorToolRecordVo.class, response);
}
/**
* 获取分包方工器具记录详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:contractorToolRecord:query")
@GetMapping("/{id}")
public R<SubContractorToolRecordVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(contractorToolRecordService.queryById(id));
}
/**
* 新增分包方工器具记录
*/
@SaCheckPermission("contractor:contractorToolRecord:add")
@Log(title = "分包方工器具记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@RequestBody SubContractorToolRecordCreateReq req) {
return R.ok(contractorToolRecordService.insertByBo(req));
}
/**
* 修改分包方工器具记录
*/
@SaCheckPermission("contractor:contractorToolRecord:edit")
@Log(title = "分包方工器具记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@RequestBody SubContractorToolRecordUpdateReq req) {
return toAjax(contractorToolRecordService.updateByBo(req));
}
/**
* 删除分包方工器具记录
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:contractorToolRecord:remove")
@Log(title = "分包方工器具记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(contractorToolRecordService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,95 @@
package org.dromara.contractor.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.subcontract.SubSubcontractCreateReq;
import org.dromara.contractor.domain.dto.subcontract.SubSubcontractQueryReq;
import org.dromara.contractor.domain.dto.subcontract.SubSubcontractUpdateReq;
import org.dromara.contractor.domain.vo.subcontract.SubSubcontractVo;
import org.dromara.contractor.service.ISubSubcontractService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 分包合同
*
* @author lilemy
* @date 2025-06-25
*/
@Validated
@RestController
@RequestMapping("/contractor/subcontract")
public class SubSubcontractController extends BaseController {
@Resource
private ISubSubcontractService subcontractService;
/**
* 查询分包合同列表
*/
@SaCheckPermission("contractor:subcontract:list")
@GetMapping("/list")
public TableDataInfo<SubSubcontractVo> list(SubSubcontractQueryReq req, PageQuery pageQuery) {
return subcontractService.queryPageList(req, pageQuery);
}
/**
* 获取分包合同详细信息
*
* @param id 主键
*/
@SaCheckPermission("contractor:subcontract:query")
@GetMapping("/{id}")
public R<SubSubcontractVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(subcontractService.queryById(id));
}
/**
* 新增分包合同
*/
@SaCheckPermission("contractor:subcontract:add")
@Log(title = "分包合同", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody SubSubcontractCreateReq req) {
return R.ok(subcontractService.insertByBo(req));
}
/**
* 修改分包合同
*/
@SaCheckPermission("contractor:subcontract:edit")
@Log(title = "分包合同", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SubSubcontractUpdateReq req) {
return toAjax(subcontractService.updateByBo(req));
}
/**
* 删除分包合同
*
* @param ids 主键串
*/
@SaCheckPermission("contractor:subcontract:remove")
@Log(title = "分包合同", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(subcontractService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,192 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 施工人员对象 sub_construction_user
*
* @author lilemy
* @date 2025-03-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sub_construction_user")
public class SubConstructionUser extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 人脸照
*/
private String facePic;
/**
* 人员姓名
*/
private String userName;
/**
* 项目id
*/
private Long projectId;
/**
* 分包公司id
*/
private Long contractorId;
/**
* 班组id
*/
private Long teamId;
/**
* 班组名称
*/
private String teamName;
/**
* 状态0在职 1离职
*/
private String status;
/**
* 是否代打
*/
private String isPinch;
/**
* 联系电话
*/
private String phone;
/**
* 0:保密 1:男 2女
*/
private String sex;
/**
* 民族
*/
private String nation;
/**
* 身份证正面图片
*/
private String sfzFrontPic;
/**
* 身份证反面图片
*/
private String sfzBackPic;
/**
* 身份证号码
*/
private String sfzNumber;
/**
* 身份证有效开始期
*/
private String sfzStart;
/**
* 身份证有效结束期
*/
private String sfzEnd;
/**
* 身份证地址
*/
private String sfzSite;
/**
* 身份证出生日期
*/
private String sfzBirth;
/**
* 籍贯
*/
private String nativePlace;
/**
* 银行卡图片
*/
private String yhkPic;
/**
* 银行卡号
*/
private String yhkNumber;
/**
* 开户行
*/
private String yhkOpeningBank;
/**
* 持卡人
*/
private String yhkCardholder;
/**
* 工种(字典type_of_work)
*/
private String typeOfWork;
/**
* 工资计量单位
*/
private String wageMeasureUnit;
/**
* 特种工作证图片
*/
private String specialWorkPic;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
private String clock;
/**
* 入场时间
*/
private Date entryDate;
/**
* 离场时间
*/
private Date leaveDate;
/**
* 薪水
*/
private Long salary;
/**
* 用户角色
*/
private String userRole;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,60 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 施工人员文件存储对象 sub_construction_user_file
*
* @author lilemy
* @date 2025-04-01
*/
@Data
@TableName("sub_construction_user_file")
public class SubConstructionUserFile implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 文件类型
*/
private String fileType;
/**
* 文件路径
*/
private String path;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,81 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
/**
* 分包单位对象 sub_contractor
*
* @author lilemy
* @date 2025-03-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sub_contractor")
public class SubContractor extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 部门id
*/
private Long deptId;
/**
* 公司名称
*/
private String name;
/**
* 负责人
*/
private String principal;
/**
* 负责人联系电话
*/
private String principalPhone;
/**
* 管理人
*/
private String custodian;
/**
* 管理人联系电话
*/
private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/**
* 公司相关文件
*/
private String files;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,77 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* 分包方物料对象 sub_contractor_material
*
* @author lilemy
* @date 2025-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sub_contractor_material")
public class SubContractorMaterial extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 物料名称
*/
private String materialName;
/**
* 物料类型
*/
private String materialType;
/**
* 物料型号
*/
private String materialModel;
/**
* 物料数量
*/
private BigDecimal materialNumber;
/**
* 物料单位
*/
private String materialUnit;
/**
* 文件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,83 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包方物料记录对象 sub_contractor_material_record
*
* @author lilemy
* @date 2025-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sub_contractor_material_record")
public class SubContractorMaterialRecord extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 物料id
*/
private Long contractorMaterialId;
/**
* 记录类型(1到货计划 2使用情况)
*/
private String recordType;
/**
* 记录时间
*/
private Date recordTime;
/**
* 数量
*/
private BigDecimal recordNumber;
/**
* 剩余数量(到货 使用)
*/
private BigDecimal remainingNumber;
/**
* 使用位置或构件部位(使用情况)
*/
private String usedPosition;
/**
* 相关附件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,72 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* 分包方工器具对象 sub_contractor_tool
*
* @author lilemy
* @date 2025-06-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sub_contractor_tool")
public class SubContractorTool extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 工具名称
*/
private String toolName;
/**
* 工具类型
*/
private String toolType;
/**
* 工具型号
*/
private String toolModel;
/**
* 工具数量
*/
private BigDecimal toolNumber;
/**
* 文件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,97 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.json.handler.BigDecimalToIntegerSerializer;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包方工器具记录对象 sub_contractor_tool_record
*
* @author lilemy
* @date 2025-06-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sub_contractor_tool_record")
public class SubContractorToolRecord extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 分包方工器具id
*/
private Long contractorToolId;
/**
* 记录类型(1进场 2出场)
*/
private String recordType;
/**
* 记录工器具数量
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal recordNumber;
/**
* 剩余数量
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal remainingNumber;
/**
* 检测编号
*/
private String checkNum;
/**
* 检测部门
*/
private String checkDept;
/**
* 检测时间
*/
private Date checkTime;
/**
* 合格证
*/
private String certificate;
/**
* 备注
*/
private String remark;
/**
* 记录时间
*/
private Date recordTime;
}

View File

@ -0,0 +1,86 @@
package org.dromara.contractor.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包合同对象 sub_subcontract
*
* @author lilemy
* @date 2025-06-25
*/
@Data
@TableName("sub_subcontract")
public class SubSubcontract implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
private Date contractTime;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -0,0 +1,30 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/7 15:04
*/
@Data
public class SubConstructionUserAttendanceMonthReq implements Serializable {
@Serial
private static final long serialVersionUID = -1496942176392426636L;
/**
* id
*/
@NotNull(message = "用户主键不能为空")
private Long userId;
/**
* 打卡月份
*/
private String clockMonth;
}

View File

@ -0,0 +1,45 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/7 10:52
*/
@Data
public class SubConstructionUserAttendanceQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -6634291825924626633L;
/**
* 人员姓名
*/
private String userName;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
/**
* 班组id
*/
private Long teamId;
/**
* 工种
*/
private String typeOfWork;
/**
* 打卡月份
*/
private String clockDate;
}

View File

@ -0,0 +1,32 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 根据项目id一键开关施工人员打卡状态
*
* @author lilemy
* @date 2025/4/2 9:14
*/
@Data
public class SubConstructionUserBatchUpdateClockReq implements Serializable {
@Serial
private static final long serialVersionUID = -5803749609177642435L;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
@NotNull(message = "打卡状态不能为空")
private String clock;
}

View File

@ -0,0 +1,34 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 批量修改施工人员状态请求对象
*
* @author lilemy
* @date 2025/4/1 17:11
*/
@Data
public class SubConstructionUserBatchUpdateStatusReq implements Serializable {
@Serial
private static final long serialVersionUID = -3756685899069233313L;
/**
* 主键id列表
*/
@NotNull(message = "主键id列表不能为空")
private List<Long> idList;
/**
* 状态0在职 1离职
*/
@NotNull(message = "状态不能为空")
private String status;
}

View File

@ -0,0 +1,37 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 施工人员迁移请求对象
*
* @author lilemy
* @date 2025/3/31 14:50
*/
@Data
public class SubConstructionUserChangeProjectReq implements Serializable {
@Serial
private static final long serialVersionUID = -2638471692809830501L;
/**
* 主键
*/
@NotNull(message = "主键id不能为空")
private Long id;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
/**
* 分包公司id
*/
@NotNull(message = "分包公司id不能为空")
private Long contractorId;
}

View File

@ -0,0 +1,153 @@
package org.dromara.contractor.domain.dto.constructionuser;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/3/5 14:05
*/
@Data
public class SubConstructionUserCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -7603153089205421154L;
/**
* 人脸照
*/
private String facePic;
/**
* 人员姓名
*/
private String userName;
/**
* 项目id
*/
private Long projectId;
/**
* 分包公司id
*/
private Long contractorId;
/**
* 状态0在职 1离职
*/
private String status;
/**
* 是否代打
*/
private String isPinch;
/**
* 联系电话
*/
private String phone;
/**
* 0:保密 1:男 2女
*/
private String sex;
/**
* 民族
*/
private String nation;
/**
* 身份证正面图片
*/
private String sfzFrontPic;
/**
* 身份证反面图片
*/
private String sfzBackPic;
/**
* 身份证号码
*/
private String sfzNumber;
/**
* 身份证有效开始期
*/
private String sfzStart;
/**
* 身份证有效结束期
*/
private String sfzEnd;
/**
* 身份证地址
*/
private String sfzSite;
/**
* 身份证出生日期
*/
private String sfzBirth;
/**
* 籍贯
*/
private String nativePlace;
/**
* 银行卡图片
*/
private String yhkPic;
/**
* 银行卡号
*/
private String yhkNumber;
/**
* 开户行
*/
private String yhkOpeningBank;
/**
* 持卡人
*/
private String yhkCardholder;
/**
* 工种(字典type_of_work)
*/
private String typeOfWork;
/**
* 工资计量单位
*/
private String wageMeasureUnit;
/**
* 特种工作证图片
*/
private String specialWorkPic;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
private String clock;
/**
* 薪水
*/
private Long salary;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,25 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/28 9:40
*/
@Data
public class SubConstructionUserGisReq implements Serializable {
@Serial
private static final long serialVersionUID = 2487357135566518535L;
/**
* 项目id
*/
@NotNull(message = "项目主键不能为空")
private Long projectId;
}

View File

@ -0,0 +1,108 @@
package org.dromara.contractor.domain.dto.constructionuser;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/3/5 14:31
*/
@Data
public class SubConstructionUserQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 3252651952758479341L;
/**
* 主键id
*/
private Long id;
/**
* 人员姓名
*/
private String userName;
/**
* 项目id
*/
private Long projectId;
/**
* 分包公司id
*/
private Long contractorId;
/**
* 班组id
*/
private Long teamId;
/**
* 不在班组id
*/
private Long notTeamId;
/**
* 班组名称
*/
private String teamName;
/**
* 状态0在职 1离职
*/
private String status;
/**
* 是否代打
*/
private String isPinch;
/**
* 0:保密 1:男 2女
*/
private String sex;
/**
* 民族
*/
private String nation;
/**
* 籍贯
*/
private String nativePlace;
/**
* 开户行
*/
private String yhkOpeningBank;
/**
* 工种(字典type_of_work)
*/
private String typeOfWork;
/**
* 工资计量单位
*/
private String wageMeasureUnit;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
private String clock;
/**
* 用户角色
*/
private String userRole;
/**
* 不是用户角色
*/
private String notUserRole;
}

View File

@ -0,0 +1,32 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 更新施工人员打卡状态
*
* @author lilemy
* @date 2025/4/2 9:14
*/
@Data
public class SubConstructionUserUpdateClockReq implements Serializable {
@Serial
private static final long serialVersionUID = -5803749609177642435L;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空")
private Long id;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
@NotNull(message = "打卡状态不能为空")
private String clock;
}

View File

@ -0,0 +1,150 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/3/5 15:04
*/
@Data
public class SubConstructionUserUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -8022860866890925958L;
/**
* 主键id
*/
@NotNull(message = "主键id不能为空")
private Long id;
/**
* 人脸照
*/
private String facePic;
/**
* 人员姓名
*/
private String userName;
/**
* 项目id
*/
private Long projectId;
/**
* 分包公司id
*/
private Long contractorId;
/**
* 状态0在职 1离职
*/
private String status;
/**
* 是否代打
*/
private String isPinch;
/**
* 联系电话
*/
private String phone;
/**
* 0:保密 1:男 2女
*/
private String sex;
/**
* 民族
*/
private String nation;
/**
* 身份证正面图片
*/
private String sfzFrontPic;
/**
* 身份证反面图片
*/
private String sfzBackPic;
/**
* 身份证有效开始期
*/
private String sfzStart;
/**
* 身份证有效结束期
*/
private String sfzEnd;
/**
* 身份证地址
*/
private String sfzSite;
/**
* 身份证出生日期
*/
private String sfzBirth;
/**
* 籍贯
*/
private String nativePlace;
/**
* 银行卡图片
*/
private String yhkPic;
/**
* 开户行
*/
private String yhkOpeningBank;
/**
* 持卡人
*/
private String yhkCardholder;
/**
* 工种(字典type_of_work)
*/
private String typeOfWork;
/**
* 工资计量单位
*/
private String wageMeasureUnit;
/**
* 特种工作证图片
*/
private String specialWorkPic;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
private String clock;
/**
* 薪水
*/
private Long salary;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,30 @@
package org.dromara.contractor.domain.dto.constructionuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/2 11:35
*/
@Data
public class SubConstructionUserUpdateSalaryReq implements Serializable {
@Serial
private static final long serialVersionUID = -1300674086812422523L;
/**
* 主键id
*/
@NotNull(message = "主键不能为空")
private Long id;
/**
* 薪水
*/
private Long salary;
}

View File

@ -0,0 +1,38 @@
package org.dromara.contractor.domain.dto.constructionuserfile;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/1 10:06
*/
@Data
public class SubConstructionUserFileQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 552027602186820020L;
/**
* 主键id
*/
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 文件类型
*/
private String fileType;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,26 @@
package org.dromara.contractor.domain.dto.constructionuserfile;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lilemy
* @date 2025/4/1 15:21
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SubConstructionUserFileReq {
/**
* 文件类型
*/
private String fileType;
/**
* 文件id
*/
private String fileId;
}

View File

@ -0,0 +1,29 @@
package org.dromara.contractor.domain.dto.constructionuserfile;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author lilemy
* @date 2025/4/1 10:01
*/
@Data
public class SubConstructionUserFileSaveReq implements Serializable {
@Serial
private static final long serialVersionUID = 4319620202781413796L;
/**
* 用户id
*/
private Long userId;
/**
* 文件列表
*/
private List<SubConstructionUserFileReq> fileList;
}

View File

@ -0,0 +1,56 @@
package org.dromara.contractor.domain.dto.constructionuserfile;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author lilemy
* @date 2025/4/9 9:25
*/
@Data
public class SubConstructionUserFileTemplateReq implements Serializable {
@Serial
private static final long serialVersionUID = -6895109153171403950L;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
/**
* 用户名
*/
private String userName;
/**
* 分包单位id
*/
private Long contractorId;
/**
* 班组id
*/
private Long teamId;
/**
* 工种
*/
private String typeOfWork;
/**
* 打卡
*/
private String clock;
/**
* 用户id列表
*/
private List<Long> userIdList;
}

View File

@ -0,0 +1,64 @@
package org.dromara.contractor.domain.dto.contractor;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Map;
/**
* @author lilemy
* @date 2025/3/5 14:05
*/
@Data
public class SubContractorCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -7603153089205421154L;
/**
* 项目id
*/
private Long projectId;
/**
* 公司名称
*/
private String name;
/**
* 负责人
*/
private String principal;
/**
* 负责人联系电话
*/
private String principalPhone;
/**
* 管理人
*/
private String custodian;
/**
* 管理人联系电话
*/
private String custodianPhone;
/**
* 公司相关文件
*/
private Map<String, Long> fileMap;
/**
* 分包类型
*/
private String contractorType;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,63 @@
package org.dromara.contractor.domain.dto.contractor;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/3/5 14:31
*/
@Data
public class SubContractorQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 3252651952758479341L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 公司名称
*/
private String name;
/**
* 负责人
*/
private String principal;
/**
* 负责人联系电话
*/
private String principalPhone;
/**
* 管理人
*/
private String custodian;
/**
* 管理人联系电话
*/
private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,69 @@
package org.dromara.contractor.domain.dto.contractor;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Map;
/**
* @author lilemy
* @date 2025/3/5 15:04
*/
@Data
public class SubContractorUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -8022860866890925958L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 公司名称
*/
private String name;
/**
* 负责人
*/
private String principal;
/**
* 负责人联系电话
*/
private String principalPhone;
/**
* 管理人
*/
private String custodian;
/**
* 管理人联系电话
*/
private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/**
* 公司相关文件
*/
private Map<String, Long> fileMap;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,58 @@
package org.dromara.contractor.domain.dto.contractormaterial;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/27 14:18
*/
@Data
public class SubContractorMaterialCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -5984785792671407395L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 物料名称
*/
private String materialName;
/**
* 物料类型
*/
private String materialType;
/**
* 物料型号
*/
private String materialModel;
/**
* 物料单位
*/
private String materialUnit;
/**
* 文件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,43 @@
package org.dromara.contractor.domain.dto.contractormaterial;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/27 14:20
*/
@Data
public class SubContractorMaterialQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 640474123189874263L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 物料名称
*/
private String materialName;
/**
* 物料类型
*/
private String materialType;
/**
* 物料型号
*/
private String materialModel;
}

View File

@ -0,0 +1,63 @@
package org.dromara.contractor.domain.dto.contractormaterial;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/27 14:20
*/
@Data
public class SubContractorMaterialUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -4488270790673814590L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 物料名称
*/
private String materialName;
/**
* 物料类型
*/
private String materialType;
/**
* 物料型号
*/
private String materialModel;
/**
* 物料单位
*/
private String materialUnit;
/**
* 文件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,57 @@
package org.dromara.contractor.domain.dto.contractormaterialrecord;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025/6/27 14:35
*/
@Data
public class SubContractorMaterialRecordCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -2325294573057427849L;
/**
* 物料id
*/
private Long contractorMaterialId;
/**
* 记录类型(1到货计划 2使用情况)
*/
private String recordType;
/**
* 记录时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date recordTime;
/**
* 数量
*/
private BigDecimal recordNumber;
/**
* 使用位置或构件部位(使用情况)
*/
private String usedPosition;
/**
* 相关附件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,43 @@
package org.dromara.contractor.domain.dto.contractormaterialrecord;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/27 14:36
*/
@Data
public class SubContractorMaterialRecordQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -5817912360176038347L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 物料id
*/
private Long contractorMaterialId;
/**
* 记录类型(1到货计划 2使用情况)
*/
private String recordType;
/**
* 使用位置或构件部位(使用情况)
*/
private String usedPosition;
}

View File

@ -0,0 +1,62 @@
package org.dromara.contractor.domain.dto.contractormaterialrecord;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025/6/27 14:36
*/
@Data
public class SubContractorMaterialRecordUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -6087029523445301396L;
/**
* 主键id
*/
private Long id;
/**
* 物料id
*/
private Long contractorMaterialId;
/**
* 记录类型(1到货计划 2使用情况)
*/
private String recordType;
/**
* 记录时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date recordTime;
/**
* 数量
*/
private BigDecimal recordNumber;
/**
* 使用位置或构件部位(使用情况)
*/
private String usedPosition;
/**
* 相关附件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,59 @@
package org.dromara.contractor.domain.dto.contractortool;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025/6/26 15:26
*/
@Data
public class SubContractorToolCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -148571725751082526L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 工具名称
*/
private String toolName;
/**
* 工具类型
*/
private String toolType;
/**
* 工具型号
*/
private String toolModel;
/**
* 工具数量
*/
private BigDecimal toolNumber;
/**
* 文件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,43 @@
package org.dromara.contractor.domain.dto.contractortool;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/26 15:26
*/
@Data
public class SubContractorToolQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -654101391027815665L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 工具名称
*/
private String toolName;
/**
* 工具类型
*/
private String toolType;
/**
* 工具型号
*/
private String toolModel;
}

View File

@ -0,0 +1,64 @@
package org.dromara.contractor.domain.dto.contractortool;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025/6/26 15:26
*/
@Data
public class SubContractorToolUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = 6147452720586538283L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 工具名称
*/
private String toolName;
/**
* 工具类型
*/
private String toolType;
/**
* 工具型号
*/
private String toolModel;
/**
* 工具数量
*/
private BigDecimal toolNumber;
/**
* 文件
*/
private String file;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,67 @@
package org.dromara.contractor.domain.dto.contractortoolentry;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025/6/26 17:52
*/
@Data
public class SubContractorToolRecordCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = 8161480499208093948L;
/**
* 分包方工器具id
*/
private Long contractorToolId;
/**
* 记录类型(1进场 2出场)
*/
private String recordType;
/**
* 记录工器具数量
*/
private BigDecimal recordNumber;
/**
* 检测编号
*/
private String checkNum;
/**
* 检测部门
*/
private String checkDept;
/**
* 检测时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date checkTime;
/**
* 合格证
*/
private String certificate;
/**
* 备注
*/
private String remark;
/**
* 记录时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date recordTime;
}

View File

@ -0,0 +1,48 @@
package org.dromara.contractor.domain.dto.contractortoolentry;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/26 17:52
*/
@Data
public class SubContractorToolRecordQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -5521479525294608178L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 分包方工器具id
*/
private Long contractorToolId;
/**
* 检测编号
*/
private String checkNum;
/**
* 检测部门
*/
private String checkDept;
/**
* 记录类型
*/
private String recordType;
}

View File

@ -0,0 +1,63 @@
package org.dromara.contractor.domain.dto.contractortoolentry;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025/6/26 17:52
*/
@Data
public class SubContractorToolRecordUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = 5280254073638207854L;
/**
* 主键id
*/
private Long id;
/**
* 记录工器具数量
*/
private BigDecimal recordNumber;
/**
* 检测编号
*/
private String checkNum;
/**
* 检测部门
*/
private String checkDept;
/**
* 检测时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date checkTime;
/**
* 合格证
*/
private String certificate;
/**
* 备注
*/
private String remark;
/**
* 记录时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date recordTime;
}

View File

@ -0,0 +1,67 @@
package org.dromara.contractor.domain.dto.subcontract;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025/6/25 16:36
*/
@Data
public class SubSubcontractCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -3386090526440868496L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date contractTime;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,43 @@
package org.dromara.contractor.domain.dto.subcontract;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/6/25 16:37
*/
@Data
public class SubSubcontractQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 3731492397283570840L;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
}

View File

@ -0,0 +1,72 @@
package org.dromara.contractor.domain.dto.subcontract;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025/6/25 16:37
*/
@Data
public class SubSubcontractUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -5617446079713109912L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date contractTime;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,25 @@
package org.dromara.contractor.domain.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025/4/3 17:47
*/
@Getter
public enum SubConstructionUserFileStatusEnum {
NOUPLOAD("未上传", "1"),
PARTUPLOAD("部分上传", "2"),
UPLOAD("已上传", "3");
private final String text;
private final String value;
SubConstructionUserFileStatusEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,23 @@
package org.dromara.contractor.domain.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025/6/27 10:30
*/
@Getter
public enum SubContractorRecordEnum {
PUT("进场/入库", "1"),
OUT("出场/出库", "2");
private final String text;
private final String value;
SubContractorRecordEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,127 @@
package org.dromara.contractor.domain.exportvo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.contractor.domain.SubConstructionUser;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lilemy
* @date 2025/4/2 14:46
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubConstructionUser.class)
public class BusConstructionUserExportVo implements Serializable {
@Serial
private static final long serialVersionUID = -7147024838012426821L;
/**
* 姓名
*/
@ExcelProperty(value = "姓名")
private String userName;
/**
* 项目名称
*/
@ExcelProperty(value = "项目")
private String projectName;
/**
* 分包公司
*/
@ExcelProperty(value = "分包公司")
private String contractorName;
/**
* 班组
*/
@ExcelProperty(value = "班组")
private String teamName;
/**
* 状态0在职 1离职
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=在职,1=离职")
private String status;
/**
* 联系电话
*/
@ExcelProperty(value = "联系电话")
private String phone;
/**
* 0:保密 1:男 2女
*/
@ExcelProperty(value = "性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "user_sex_type")
private String sex;
/**
* 民族
*/
@ExcelProperty(value = "民族")
private String nation;
/**
* 身份证号码
*/
@ExcelProperty(value = "身份证号码")
private String sfzNumber;
/**
* 身份证地址
*/
@ExcelProperty(value = "身份证地址")
private String sfzSite;
/**
* 银行卡号
*/
@ExcelProperty(value = "银行卡号")
private String yhkNumber;
/**
* 工种
*/
@ExcelProperty(value = "工种", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "type_of_work")
private String typeOfWork;
/**
* 工资计量单位
*/
@ExcelProperty(value = "工资计量单位", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "wage_measure_unit_type")
private String wageMeasureUnit;
/**
* 入场时间
*/
@ExcelProperty(value = "入场时间")
private Date entryDate;
/**
* 离场时间
*/
@ExcelProperty(value = "离场时间")
private Date leaveDate;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,71 @@
package org.dromara.contractor.domain.vo.constructionuser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.project.domain.BusAttendance;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import java.util.Date;
import java.util.List;
/**
* @author lilemy
* @date 2025/4/8 17:38
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SubConstructionUserAttendanceByDay {
/**
* 上班打卡时间
*/
private Date upClockTime;
/**
* 上班打卡图片id
*/
private Long upClockPicId;
/**
* 上班打卡图片
*/
private String upClockPic;
/**
* 下班打卡图片id
*/
private Long downClockPicId;
/**
* 下班打卡图片
*/
private String downClockPic;
/**
* 下班打卡时间
*/
private Date downClockTime;
public static SubConstructionUserAttendanceByDay build(List<BusAttendance> attendanceList) {
if (attendanceList == null) {
return null;
}
SubConstructionUserAttendanceByDay constructionUserAttendanceByDay = new SubConstructionUserAttendanceByDay();
for (BusAttendance attendance : attendanceList) {
if (attendance.getCommuter().equals(BusAttendanceCommuterEnum.CLOCKIN.getValue())) {
constructionUserAttendanceByDay.setUpClockTime(attendance.getClockTime());
if (attendance.getFacePic() != null) {
constructionUserAttendanceByDay.setUpClockPicId(Long.valueOf(attendance.getFacePic()));
}
} else if (attendance.getCommuter().equals(BusAttendanceCommuterEnum.CLOCKOUT.getValue())) {
constructionUserAttendanceByDay.setDownClockTime(attendance.getClockTime());
if (attendance.getFacePic() != null) {
constructionUserAttendanceByDay.setDownClockPicId(Long.valueOf(attendance.getFacePic()));
}
}
}
return constructionUserAttendanceByDay;
}
}

View File

@ -0,0 +1,43 @@
package org.dromara.contractor.domain.vo.constructionuser;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lilemy
* @date 2025/4/7 15:06
*/
@Data
public class SubConstructionUserAttendanceMonthVo implements Serializable {
@Serial
private static final long serialVersionUID = -413447291128760025L;
/**
* 主键id
*/
private Long id;
/**
* 打卡日期
*/
@JsonFormat(shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd",
timezone = "GMT+8")
private Date clockDate;
/**
* 当天打卡状态
*/
private String Status;
/**
* 当天打卡记录
*/
private SubConstructionUserAttendanceByDay clockList;
}

View File

@ -0,0 +1,69 @@
package org.dromara.contractor.domain.vo.constructionuser;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/7 10:16
*/
@Data
public class SubConstructionUserAttendanceTotalVo implements Serializable {
@Serial
private static final long serialVersionUID = 1335094839733429171L;
/**
* 主键id
*/
private Long id;
/**
* 人员姓名
*/
private String userName;
/**
* 班组id
*/
private Long teamId;
/**
* 班组名称
*/
private String teamName;
/**
* 工种
*/
private String typeOfWork;
/**
* 出勤天数
*/
private Integer attendanceDays;
/**
* 迟到天数
*/
private Integer lateDays;
/**
* 早退天数
*/
private Integer leaveEarlyDays;
/**
* 缺卡天数
*/
private Integer unClockDays;
/**
* 请假天数
*/
private Integer leaveDays;
}

View File

@ -0,0 +1,33 @@
package org.dromara.contractor.domain.vo.constructionuser;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025/4/28 9:33
*/
@Data
public class SubConstructionUserGisVo implements Serializable {
@Serial
private static final long serialVersionUID = -3496633845665259321L;
/**
* 施工人员数量
*/
private Long peopleCount;
/**
* 出勤人员数量
*/
private Long attendanceCount;
/**
* 出勤率
*/
private String attendanceRate;
}

View File

@ -0,0 +1,262 @@
package org.dromara.contractor.domain.vo.constructionuser;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.domain.vo.contractor.SubContractorVo;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 施工人员视图对象 bus_construction_user
*
* @author lilemy
* @date 2025-03-07
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubConstructionUser.class)
public class SubConstructionUserVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 人脸照
*/
@ExcelProperty(value = "人脸照")
private String facePic;
/**
* 人脸照 url
*/
@ExcelProperty(value = "人脸照 url")
private String facePicUrl;
/**
* 人员姓名
*/
@ExcelProperty(value = "人员姓名")
private String userName;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 分包公司id
*/
@ExcelProperty(value = "分包公司id")
private Long contractorId;
/**
* 分包公司
*/
private SubContractorVo contractorVo;
/**
* 班组id
*/
@ExcelProperty(value = "班组id")
private Long teamId;
/**
* 班组名称
*/
@ExcelProperty(value = "班组名称")
private String teamName;
/**
* 状态0在职 1离职
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=在职,1=离职")
private String status;
/**
* 是否代打
*/
@ExcelProperty(value = "是否代打")
private String isPinch;
/**
* 联系电话
*/
@ExcelProperty(value = "联系电话")
private String phone;
/**
* 0:保密 1:男 2女
*/
@ExcelProperty(value = "性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "user_sex_type")
private String sex;
/**
* 民族
*/
@ExcelProperty(value = "民族")
private String nation;
/**
* 身份证正面图片
*/
@ExcelProperty(value = "身份证正面图片")
private String sfzFrontPic;
/**
* 身份证反面图片
*/
@ExcelProperty(value = "身份证反面图片")
private String sfzBackPic;
/**
* 身份证号码
*/
@ExcelProperty(value = "身份证号码")
private String sfzNumber;
/**
* 身份证有效开始期
*/
@ExcelProperty(value = "身份证有效开始期")
private String sfzStart;
/**
* 身份证有效结束期
*/
@ExcelProperty(value = "身份证有效结束期")
private String sfzEnd;
/**
* 身份证地址
*/
@ExcelProperty(value = "身份证地址")
private String sfzSite;
/**
* 身份证出生日期
*/
@ExcelProperty(value = "身份证出生日期")
private String sfzBirth;
/**
* 籍贯
*/
@ExcelProperty(value = "籍贯")
private String nativePlace;
/**
* 银行卡图片
*/
@ExcelProperty(value = "银行卡图片")
private String yhkPic;
/**
* 银行卡号
*/
@ExcelProperty(value = "银行卡号")
private String yhkNumber;
/**
* 开户行
*/
@ExcelProperty(value = "开户行")
private String yhkOpeningBank;
/**
* 持卡人
*/
@ExcelProperty(value = "持卡人")
private String yhkCardholder;
/**
* 工种
*/
@ExcelProperty(value = "工种", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "type_of_work")
private String typeOfWork;
/**
* 工资计量单位
*/
@ExcelProperty(value = "工资计量单位", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "wage_measure_unit_type")
private String wageMeasureUnit;
/**
* 特种工作证图片
*/
@ExcelProperty(value = "特种工作证图片")
private String specialWorkPic;
/**
* 打卡(0启用打卡 1禁止打卡)
*/
@ExcelProperty(value = "打卡(0启用打卡 1禁止打卡)")
private String clock;
/**
* 入场时间
*/
@ExcelProperty(value = "入场时间")
private Date entryDate;
/**
* 离场时间
*/
@ExcelProperty(value = "离场时间")
private Date leaveDate;
/**
* 标准薪水
*/
@ExcelProperty(value = "标准薪水")
private Long standardSalary;
/**
* 薪水
*/
@ExcelProperty(value = "薪水")
private Long salary;
/**
* 用户角色
*/
private String userRole;
/**
* 文件上传状态
*/
@ExcelProperty(value = "文件上传状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "user_file_status_type")
private String fileUploadStatus;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,60 @@
package org.dromara.contractor.domain.vo.constructionuserfile;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.contractor.domain.SubConstructionUserFile;
import java.io.Serial;
import java.io.Serializable;
/**
* 施工人员文件存储视图对象 bus_construction_user_file
*
* @author lilemy
* @date 2025-04-01
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubConstructionUserFile.class)
public class SubConstructionUserFileVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 文件类型
*/
@ExcelProperty(value = "文件类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "user_file_type")
private String fileType;
/**
* 文件路径
*/
@ExcelProperty(value = "文件路径")
private String path;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,94 @@
package org.dromara.contractor.domain.vo.contractor;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.contractor.domain.SubContractor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
/**
* 分包单位视图对象 sub_contractor
*
* @author lilemy
* @date 2025-03-07
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubContractor.class)
public class SubContractorVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 公司名称
*/
@ExcelProperty(value = "公司名称")
private String name;
/**
* 负责人
*/
@ExcelProperty(value = "负责人")
private String principal;
/**
* 负责人联系电话
*/
@ExcelProperty(value = "负责人联系电话")
private String principalPhone;
/**
* 管理人
*/
@ExcelProperty(value = "管理人")
private String custodian;
/**
* 管理人联系电话
*/
@ExcelProperty(value = "管理人联系电话")
private String custodianPhone;
/**
* 分包类型
*/
private String contractorType;
/**
* 公司相关文件
*/
@ExcelProperty(value = "公司相关文件")
private Map<String, Long> fileMap;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,97 @@
package org.dromara.contractor.domain.vo.contractormaterial;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.contractor.domain.SubContractorMaterial;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 分包方物料视图对象 sub_contractor_material
*
* @author lilemy
* @date 2025-06-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubContractorMaterial.class)
public class SubContractorMaterialVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 分包方id
*/
@ExcelProperty(value = "分包方id")
private Long contractorId;
/**
* 分包方名称
*/
private String contractorName;
/**
* 物料名称
*/
@ExcelProperty(value = "物料名称")
private String materialName;
/**
* 物料类型
*/
@ExcelProperty(value = "物料类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "contractor_material_type")
private String materialType;
/**
* 物料型号
*/
@ExcelProperty(value = "物料型号")
private String materialModel;
/**
* 物料数量
*/
@ExcelProperty(value = "物料数量")
private BigDecimal materialNumber;
/**
* 物料单位
*/
@ExcelProperty(value = "物料单位")
private String materialUnit;
/**
* 文件
*/
@ExcelProperty(value = "文件")
private String file;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,109 @@
package org.dromara.contractor.domain.vo.contractormaterialrecord;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.contractor.domain.SubContractorMaterialRecord;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包方物料记录视图对象 sub_contractor_material_record
*
* @author lilemy
* @date 2025-06-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubContractorMaterialRecord.class)
public class SubContractorMaterialRecordVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 分包方id
*/
@ExcelProperty(value = "分包方id")
private Long contractorId;
/**
* 分包方名称
*/
private String contractorName;
/**
* 物料id
*/
@ExcelProperty(value = "物料id")
private Long contractorMaterialId;
/**
* 物料名称
*/
private String contractorMaterialName;
/**
* 记录类型(1到货计划 2使用情况)
*/
@ExcelProperty(value = "记录类型(1到货计划 2使用情况)", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "contractor_material_record_type")
private String recordType;
/**
* 记录时间
*/
@ExcelProperty(value = "记录时间")
private Date recordTime;
/**
* 数量
*/
@ExcelProperty(value = "数量")
private BigDecimal recordNumber;
/**
* 剩余数量(到货 使用)
*/
@ExcelProperty(value = "剩余数量(到货 使用)")
private BigDecimal remainingNumber;
/**
* 使用位置或构件部位(使用情况)
*/
@ExcelProperty(value = "使用位置或构件部位(使用情况)")
private String usedPosition;
/**
* 相关附件
*/
@ExcelProperty(value = "相关附件")
private String file;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,91 @@
package org.dromara.contractor.domain.vo.contractortool;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.contractor.domain.SubContractorTool;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包方工器具视图对象 sub_contractor_tool
*
* @author lilemy
* @date 2025-06-26
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubContractorTool.class)
public class SubContractorToolVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 分包方id
*/
@ExcelProperty(value = "分包方id")
private Long contractorId;
/**
* 分包方名称
*/
private String contractorName;
/**
* 工具名称
*/
@ExcelProperty(value = "工具名称")
private String toolName;
/**
* 工具类型
*/
@ExcelProperty(value = "工具类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "contractor_tool_type")
private String toolType;
/**
* 工具型号
*/
@ExcelProperty(value = "工具型号")
private String toolModel;
/**
* 工具数量
*/
@ExcelProperty(value = "工具数量")
private BigDecimal toolNumber;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,120 @@
package org.dromara.contractor.domain.vo.contractortoolentry;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.contractor.domain.SubContractorToolRecord;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包方工器具记录视图对象 sub_contractor_tool_entry
*
* @author lilemy
* @date 2025-06-26
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SubContractorToolRecord.class)
public class SubContractorToolRecordVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 分包方id
*/
@ExcelProperty(value = "分包方id")
private Long contractorId;
/**
* 分包方名称
*/
private String contractorName;
/**
* 分包方工器具id
*/
@ExcelProperty(value = "分包方工器具id")
private Long contractorToolId;
/**
* 分包方工器具名称
*/
private String contractorToolName;
/**
* 记录类型(1进场 2出场)
*/
@ExcelProperty(value = "记录类型(1进场 2出场)")
private String recordType;
/**
* 记录工器具数量
*/
@ExcelProperty(value = "记录工器具数量")
private BigDecimal recordNumber;
/**
* 剩余数量
*/
@ExcelProperty(value = "剩余数量")
private BigDecimal remainingNumber;
/**
* 检测编号
*/
@ExcelProperty(value = "检测编号")
private String checkNum;
/**
* 检测部门
*/
@ExcelProperty(value = "检测部门")
private String checkDept;
/**
* 检测时间
*/
@ExcelProperty(value = "检测时间")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date checkTime;
/**
* 合格证
*/
@ExcelProperty(value = "合格证")
private String certificate;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 记录时间
*/
@ExcelProperty(value = "记录时间")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date recordTime;
}

View File

@ -0,0 +1,81 @@
package org.dromara.contractor.domain.vo.subcontract;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.contractor.domain.SubSubcontract;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 分包合同视图对象 sub_subcontract
*
* @author lilemy
* @date 2025-06-25
*/
@Data
@AutoMapper(target = SubSubcontract.class)
public class SubSubcontractVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 分包方id
*/
private Long contractorId;
/**
* 分包方名称
*/
private String contractorName;
/**
* 合同文件id
*/
private Long contractFileId;
/**
* 合同编号
*/
private String contractNumber;
/**
* 合同名称
*/
private String contractName;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 合同时间
*/
private Date contractTime;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,84 @@
package org.dromara.contractor.interceptor;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.filter.RepeatedlyRequestWrapper;
import org.dromara.system.domain.enums.SysDeptTypeEnum;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.service.ISysDeptService;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.io.BufferedReader;
import java.util.Arrays;
import java.util.Map;
/**
* @author lilemy
* @date 2025/7/21 15:57
*/
@Component
public class ContractorInterceptor implements HandlerInterceptor {
@Resource
private ISysDeptService deptService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Long deptId = LoginHelper.getDeptId();
if (ObjectUtil.isNotNull(deptId)) {
SysDeptVo deptVo = deptService.selectDeptById(deptId);
if (deptVo.getDeptType().equals(SysDeptTypeEnum.CONTRACT.getCode())) {
// 在请求前处理逻辑
System.out.println("拦截到了 /contractor/** 请求:" + request.getRequestURI());
Long contractorId = deptVo.getContractorId();
if (isJsonRequest(request)) {
String jsonParam = "";
if (request instanceof RepeatedlyRequestWrapper) {
BufferedReader reader = request.getReader();
jsonParam = IoUtil.read(reader);
}
JSONObject jsonObject = JSONUtil.parseObj(jsonParam);
contractorId = jsonObject.getLong("contractorId");
} else {
Map<String, String[]> parameterMap = request.getParameterMap();
if (MapUtil.isNotEmpty(parameterMap)) {
String[] contractorIds = parameterMap.get("contractorId");
if (contractorIds != null && contractorIds.length != 0 && StringUtils.isNotBlank(contractorIds[0])) {
contractorId = Long.valueOf(Arrays.asList(contractorIds).getFirst());
}
}
}
if (ObjectUtil.isNull(contractorId) || !contractorId.equals(deptVo.getContractorId())) {
throw new ServiceException("无访问权限");
}
}
}
return true; // 返回 true 放行false 拦截
}
/**
* 判断本次请求的数据类型是否为json
*
* @param request request
* @return boolean
*/
private boolean isJsonRequest(HttpServletRequest request) {
String contentType = request.getContentType();
if (contentType != null) {
return StringUtils.startsWithIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE);
}
return false;
}
}

View File

@ -0,0 +1,15 @@
package org.dromara.contractor.mapper;
import org.dromara.contractor.domain.SubConstructionUserFile;
import org.dromara.contractor.domain.vo.constructionuserfile.SubConstructionUserFileVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 施工人员文件存储Mapper接口
*
* @author lilemy
* @date 2025-04-01
*/
public interface SubConstructionUserFileMapper extends BaseMapperPlus<SubConstructionUserFile, SubConstructionUserFileVo> {
}

View File

@ -0,0 +1,15 @@
package org.dromara.contractor.mapper;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 施工人员Mapper接口
*
* @author lilemy
* @date 2025-03-07
*/
public interface SubConstructionUserMapper extends BaseMapperPlus<SubConstructionUser, SubConstructionUserVo> {
}

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