Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
Y
yifu-mvp
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fangxinjiang
yifu-mvp
Commits
3ffe3bb0
Commit
3ffe3bb0
authored
Dec 17, 2025
by
huyuchen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
huych-电子档案批量导入初次提交
parent
eb755797
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
4849 additions
and
18 deletions
+4849
-18
TEmployeeInfoController.java
.../v1/yifu/archives/controller/TEmployeeInfoController.java
+13
-0
TEmployeeInfoService.java
...d/plus/v1/yifu/archives/service/TEmployeeInfoService.java
+2
-1
TEmployeeInfoServiceImpl.java
.../yifu/archives/service/impl/TEmployeeInfoServiceImpl.java
+8
-0
ArchiveConstants.java
.../yifu/cloud/plus/v1/batch/constants/ArchiveConstants.java
+141
-0
SysConfigLimit.java
...a/com/yifu/cloud/plus/v1/batch/entity/SysConfigLimit.java
+58
-0
TAttaInfo.java
...n/java/com/yifu/cloud/plus/v1/batch/entity/TAttaInfo.java
+95
-0
TElectronicArchiveDetail.java
.../cloud/plus/v1/batch/entity/TElectronicArchiveDetail.java
+153
-0
TElectronicArchiveTask.java
...fu/cloud/plus/v1/batch/entity/TElectronicArchiveTask.java
+65
-0
TTaskArchiveRelation.java
...yifu/cloud/plus/v1/batch/entity/TTaskArchiveRelation.java
+49
-0
ArchiveBatchDownloadRequestVO.java
...cloud/plus/v1/batch/vo/ArchiveBatchDownloadRequestVO.java
+60
-0
ArchiveDownloadFeedbackVO.java
...ifu/cloud/plus/v1/batch/vo/ArchiveDownloadFeedbackVO.java
+74
-0
ArchiveFeedbackVO.java
...va/com/yifu/cloud/plus/v1/batch/vo/ArchiveFeedbackVO.java
+78
-0
ArchiveImportVO.java
...java/com/yifu/cloud/plus/v1/batch/vo/ArchiveImportVO.java
+62
-0
TElectronicArchiveDetailSearchVo.java
...ud/plus/v1/batch/vo/TElectronicArchiveDetailSearchVo.java
+46
-0
TElectronicArchiveDetailVo.java
...fu/cloud/plus/v1/batch/vo/TElectronicArchiveDetailVo.java
+98
-0
TElectronicArchiveTaskSearchVo.java
...loud/plus/v1/batch/vo/TElectronicArchiveTaskSearchVo.java
+51
-0
TElectronicArchiveTaskVo.java
...yifu/cloud/plus/v1/batch/vo/TElectronicArchiveTaskVo.java
+46
-0
TaskAttachmentGroupVO.java
...om/yifu/cloud/plus/v1/batch/vo/TaskAttachmentGroupVO.java
+54
-0
pom.xml
yifu-batch/yifu-batch-biz/pom.xml
+5
-16
FileUploadController.java
.../cloud/plus/v1/batch/controller/FileUploadController.java
+134
-0
TElectronicArchiveTaskController.java
...v1/batch/controller/TElectronicArchiveTaskController.java
+177
-0
TTaskArchiveRelationController.java
...s/v1/batch/controller/TTaskArchiveRelationController.java
+53
-0
SysConfigLimitMapper.java
...yifu/cloud/plus/v1/batch/mapper/SysConfigLimitMapper.java
+24
-0
TAttaInfoMapper.java
.../com/yifu/cloud/plus/v1/batch/mapper/TAttaInfoMapper.java
+49
-0
TElectronicArchiveDetailMapper.java
.../plus/v1/batch/mapper/TElectronicArchiveDetailMapper.java
+25
-0
TElectronicArchiveTaskMapper.java
...ud/plus/v1/batch/mapper/TElectronicArchiveTaskMapper.java
+26
-0
TTaskArchiveRelationMapper.java
...loud/plus/v1/batch/mapper/TTaskArchiveRelationMapper.java
+24
-0
ElectronicArchiveImportService.java
...plus/v1/batch/service/ElectronicArchiveImportService.java
+63
-0
FileUploadService.java
...m/yifu/cloud/plus/v1/batch/service/FileUploadService.java
+32
-0
TAttaInfoService.java
...om/yifu/cloud/plus/v1/batch/service/TAttaInfoService.java
+47
-0
TElectronicArchiveDetailService.java
...lus/v1/batch/service/TElectronicArchiveDetailService.java
+58
-0
TElectronicArchiveTaskService.java
.../plus/v1/batch/service/TElectronicArchiveTaskService.java
+25
-0
TTaskArchiveRelationService.java
...ud/plus/v1/batch/service/TTaskArchiveRelationService.java
+22
-0
ElectronicArchiveImportServiceImpl.java
...atch/service/impl/ElectronicArchiveImportServiceImpl.java
+1103
-0
FileUploadServiceImpl.java
...oud/plus/v1/batch/service/impl/FileUploadServiceImpl.java
+226
-0
TAttaInfoServiceImpl.java
...loud/plus/v1/batch/service/impl/TAttaInfoServiceImpl.java
+67
-0
TElectronicArchiveDetailServiceImpl.java
...tch/service/impl/TElectronicArchiveDetailServiceImpl.java
+1014
-0
TElectronicArchiveTaskServiceImpl.java
...batch/service/impl/TElectronicArchiveTaskServiceImpl.java
+73
-0
TTaskArchiveRelationServiceImpl.java
...1/batch/service/impl/TTaskArchiveRelationServiceImpl.java
+31
-0
SysConfigLimitMapper.xml
...ch-biz/src/main/resources/mapper/SysConfigLimitMapper.xml
+19
-0
TAttaInfoMapper.xml
...u-batch-biz/src/main/resources/mapper/TAttaInfoMapper.xml
+158
-0
TElectronicArchiveDetailMapper.xml
.../main/resources/mapper/TElectronicArchiveDetailMapper.xml
+103
-0
TElectronicArchiveTaskMapper.xml
...rc/main/resources/mapper/TElectronicArchiveTaskMapper.xml
+74
-0
TTaskArchiveRelationMapper.xml
.../src/main/resources/mapper/TTaskArchiveRelationMapper.xml
+40
-0
CacheConstants.java
...oud/plus/v1/yifu/common/core/constant/CacheConstants.java
+7
-0
ArchivesDaprUtil.java
...cloud/plus/v1/yifu/common/dapr/util/ArchivesDaprUtil.java
+17
-1
No files found.
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/controller/TEmployeeInfoController.java
View file @
3ffe3bb0
...
...
@@ -161,6 +161,19 @@ public class TEmployeeInfoController {
return
tEmployeeInfoService
.
getById
(
empId
);
}
/**
* @param vo
* @Description: 内部接口获取档案基本信息
* @Author: huych
* @Date: 2025/12/17 14:47
* @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeInfo>
**/
@Inner
@PostMapping
(
"/inner/getTEmployeeInfoByIdcardAndName"
)
public
TEmployeeInfo
getTEmployeeInfoByIdcardAndName
(
@RequestBody
IdNameNoVo
vo
)
{
return
tEmployeeInfoService
.
getTEmployeeInfoByIdcardAndName
(
vo
);
}
/**
* @param idcard
* @Description: 内部接口获取档案基本信息
...
...
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/service/TEmployeeInfoService.java
View file @
3ffe3bb0
...
...
@@ -22,7 +22,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.pig4cloud.plugin.excel.vo.ErrorMessage
;
import
com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeInfo
;
import
com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeProject
;
import
com.yifu.cloud.plus.v1.yifu.archives.vo.*
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchListVO
;
...
...
@@ -213,6 +212,8 @@ public interface TEmployeeInfoService extends IService<TEmployeeInfo> {
// 未删除的档案
TEmployeeInfo
getInfoByIdcard
(
String
idcard
);
TEmployeeInfo
getTEmployeeInfoByIdcardAndName
(
IdNameNoVo
vo
);
// 已删除的档案
TEmployeeInfo
getInfoByDelete
(
String
idcard
);
...
...
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/service/impl/TEmployeeInfoServiceImpl.java
View file @
3ffe3bb0
...
...
@@ -2828,6 +2828,14 @@ public class TEmployeeInfoServiceImpl extends ServiceImpl<TEmployeeInfoMapper, T
.
last
(
CommonConstants
.
LAST_ONE_SQL
));
}
@Override
public
TEmployeeInfo
getTEmployeeInfoByIdcardAndName
(
IdNameNoVo
vo
)
{
return
baseMapper
.
selectOne
(
Wrappers
.<
TEmployeeInfo
>
query
().
lambda
()
.
eq
(
TEmployeeInfo:
:
getEmpIdcard
,
vo
.
getNo
())
.
eq
(
TEmployeeInfo:
:
getEmpName
,
vo
.
getName
())
.
last
(
CommonConstants
.
LAST_ONE_SQL
));
}
@Override
public
TEmployeeInfo
getInfoByDelete
(
String
idcard
)
{
return
baseMapper
.
selectOne
(
Wrappers
.<
TEmployeeInfo
>
query
().
lambda
()
...
...
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/constants/ArchiveConstants.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
constants
;
/**
* 电子档案相关常量
*
* @author huych
* @date 2025-12-17
*/
public
interface
ArchiveConstants
{
/**
* 任务编号前缀
*/
String
TASK_CODE_PREFIX
=
"DZDAPL"
;
/**
* 任务状态-未上传
*/
String
TASK_STATUS_NOT_UPLOADED
=
"0"
;
/**
* 任务状态-生成电子档案中
*/
String
TASK_STATUS_GENERATING
=
"1"
;
/**
* 任务状态-已生成电子档案
*/
String
TASK_STATUS_GENERATED
=
"2"
;
/**
* 明细状态-不可用
*/
String
DETAIL_STATUS_DISABLED
=
"0"
;
/**
* 明细状态-可用
*/
String
DETAIL_STATUS_ENABLED
=
"1"
;
/**
* 附件关系类型-任务表附件
*/
String
ATTA_RELATION_TYPE_TASK
=
"1"
;
/**
* 附件关系类型-ZIP附件
*/
String
ATTA_RELATION_TYPE_ZIP
=
"2"
;
/**
* 附件关系类型-反馈表附件
*/
String
ATTA_RELATION_TYPE_FEEDBACK
=
"3"
;
/**
* 附件状态-可用
*/
String
ATTA_STATUS_ENABLED
=
"0"
;
/**
* 附件状态-不可用
*/
String
ATTA_STATUS_DISABLED
=
"1"
;
/**
* 资料类型-存量
*/
String
MATERIAL_TYPE_STOCK
=
"存量"
;
/**
* 资料类型-新签
*/
String
MATERIAL_TYPE_NEW
=
"新签"
;
/**
* 资料类型-续签
*/
String
MATERIAL_TYPE_RENEW
=
"续签"
;
/**
* 资料类型-离职
*/
String
MATERIAL_TYPE_LEAVE
=
"离职"
;
/**
* 资料类型编码-存量
*/
String
MATERIAL_TYPE_CODE_STOCK
=
"0"
;
/**
* 资料类型编码-新签
*/
String
MATERIAL_TYPE_CODE_NEW
=
"1"
;
/**
* 资料类型编码-续签
*/
String
MATERIAL_TYPE_CODE_RENEW
=
"2"
;
/**
* 资料类型编码-离职
*/
String
MATERIAL_TYPE_CODE_LEAVE
=
"3"
;
/**
* 处理结果-成功
*/
String
PROCESS_RESULT_SUCCESS
=
"成功"
;
/**
* 处理结果-失败
*/
String
PROCESS_RESULT_FAILED
=
"失败"
;
/**
* 处理结果-跳过
*/
String
PROCESS_RESULT_SKIP
=
"跳过"
;
/**
* ZIP文件最大大小(500M)
*/
long
ZIP_MAX_SIZE
=
500
*
1024
*
1024L
;
/**
* 单个附件最大大小(15M)
*/
long
SINGLE_FILE_MAX_SIZE
=
15
*
1024
*
1024L
;
/**
* 同时上传任务数限制
*/
int
MAX_CONCURRENT_TASKS
=
5
;
/**
* 支持的文件格式
*/
String
[]
SUPPORTED_FILE_FORMATS
=
{
"png"
,
"jpg"
,
"jpeg"
,
"xlsx"
,
"xls"
,
"doc"
,
"docx"
,
"pdf"
,
"ppt"
,
"pptx"
,
"txt"
};
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/entity/SysConfigLimit.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
entity
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
org.hibernate.validator.constraints.Length
;
import
javax.validation.constraints.NotBlank
;
/**
* 系统限制配置表
*
* @author hgw
* @date 2024-09-24 17:39:57
*/
@Data
@TableName
(
"sys_config_limit"
)
@Schema
(
description
=
"系统限制配置表"
)
public
class
SysConfigLimit
{
/**
* id
*/
@TableId
(
type
=
IdType
.
ASSIGN_ID
)
@ExcelProperty
(
"id"
)
@Schema
(
description
=
"id"
)
private
String
id
;
/**
* 限制键
*/
@ExcelAttribute
(
name
=
"限制键"
,
isNotEmpty
=
true
,
errorInfo
=
"限制键不能为空"
,
maxLength
=
32
)
@NotBlank
(
message
=
"限制键不能为空"
)
@Length
(
max
=
32
,
message
=
"限制键不能超过32个字符"
)
@ExcelProperty
(
"限制键"
)
@Schema
(
description
=
"限制键"
)
private
String
configKey
;
/**
* 限制值
*/
@ExcelAttribute
(
name
=
"限制值"
,
isNotEmpty
=
true
,
errorInfo
=
"限制值不能为空"
)
@NotBlank
(
message
=
"限制值不能为空"
)
@ExcelProperty
(
"限制值"
)
@Schema
(
description
=
"限制值"
)
private
Integer
configValue
;
/**
* 备注
*/
@ExcelAttribute
(
name
=
"备注"
,
maxLength
=
255
)
@Length
(
max
=
255
,
message
=
"备注不能超过255个字符"
)
@ExcelProperty
(
"备注"
)
@Schema
(
description
=
"备注"
)
private
String
remark
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/entity/TAttaInfo.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
entity
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
org.hibernate.validator.constraints.Length
;
import
javax.validation.constraints.NotBlank
;
/**
* @Author fxj
* @Description 附件信息表
* @Date 11:07 2022/6/22
**/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
@TableName
(
"t_atta_info"
)
@Tag
(
name
=
"附件信息表"
)
public
class
TAttaInfo
extends
BaseEntity
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
@TableId
(
type
=
IdType
.
ASSIGN_ID
)
@Schema
(
description
=
"主键"
)
private
String
id
;
/**
* 资源名称
*/
@NotBlank
(
message
=
"资源名称不能为空"
)
@Length
(
max
=
50
,
message
=
"资源名称不能超过50个字符"
)
@Schema
(
description
=
"资源名称"
)
private
String
attaName
;
/**
* 资源地址
*/
@NotBlank
(
message
=
"资源地址不能为空"
)
@Length
(
max
=
100
,
message
=
"资源地址不能超过100个字符"
)
@Schema
(
description
=
"资源地址"
)
private
String
attaSrc
;
/**
* 资源大小
*/
@Schema
(
description
=
"资源大小"
)
private
Long
attaSize
;
/**
* 资源类型
*/
@Length
(
max
=
10
,
message
=
"资源类型不能超过10个字符"
)
@Schema
(
description
=
"资源类型"
)
private
String
attaType
;
/**
* 关系类型 1 任务表附件 2 zip附件 3反馈表附件
*/
@NotBlank
(
message
=
"关系类型不能为空"
)
@Length
(
max
=
20
,
message
=
"关系类型不能超过20个字符"
)
@Schema
(
description
=
"关系类型 1 任务表附件 2 zip附件 3反馈表附件"
)
private
String
relationType
;
/**
* 实体id和关系类型共同确定附件所属
*/
@NotBlank
(
message
=
"实体id和关系类型共同确定附件所属不能为空"
)
@Length
(
max
=
32
,
message
=
"实体id和关系类型共同确定附件所属不能超过32个字符"
)
@Schema
(
description
=
"实体id和关系类型共同确定附件所属"
)
private
String
domainId
;
/**
* 状态 0可用 1不可用
*/
@Schema
(
description
=
"状态 0可用 1不可用"
)
private
String
status
;
/**
* 地址URL
*/
@Length
(
max
=
100
,
message
=
"地址URL不能超过100个字符"
)
@Schema
(
description
=
"地址URL"
)
@TableField
(
exist
=
false
)
private
String
attaUrl
;
/**
* 附件变更类型:0 新增 1 更新 2 删除 3 不变 档案编辑附件时需要告知后端是增加还是减少
*/
@TableField
(
exist
=
false
)
private
String
handleType
;
/**
* 其他分租名称
*/
@TableField
(
exist
=
false
)
private
String
groupName
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/entity/TElectronicArchiveDetail.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
entity
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.yifu.cloud.plus.v1.batch.vo.TaskAttachmentGroupVO
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
org.hibernate.validator.constraints.Length
;
import
java.util.List
;
/**
* 电子档案明细表
*
* @author huych
* @date 2025-12-17 11:03:37
*/
@Data
@TableName
(
"t_electronic_archive_detail"
)
@EqualsAndHashCode
(
callSuper
=
true
)
@Schema
(
description
=
"电子档案明细表"
)
public
class
TElectronicArchiveDetail
extends
BaseEntity
{
/**
* 主键
*/
@TableId
(
type
=
IdType
.
ASSIGN_ID
)
@ExcelProperty
(
"主键"
)
@Schema
(
description
=
"主键"
)
private
String
id
;
/**
* 姓名
*/
@ExcelAttribute
(
name
=
"姓名"
,
maxLength
=
32
)
@ExcelProperty
(
"姓名"
)
@Schema
(
description
=
"姓名"
)
private
String
empName
;
/**
* 身份证号码
*/
@ExcelAttribute
(
name
=
"身份证号码"
)
@ExcelProperty
(
"身份证号码"
)
@Schema
(
description
=
"身份证号码"
)
private
String
empIdcard
;
/**
* 项目编码
*/
@ExcelAttribute
(
name
=
"项目编码"
)
@ExcelProperty
(
"项目编码"
)
@Schema
(
description
=
"项目编码"
)
private
String
deptNo
;
/**
* 项目名称
*/
@ExcelAttribute
(
name
=
"项目名称"
)
@ExcelProperty
(
"项目名称"
)
@Schema
(
description
=
"项目名称"
)
private
String
deptName
;
/**
* 客户名称
*/
@ExcelAttribute
(
name
=
"客户名称"
)
@ExcelProperty
(
"客户名称"
)
@Schema
(
description
=
"客户名称"
)
private
String
customerName
;
/**
* 客户编码
*/
@ExcelAttribute
(
name
=
"客户编码"
)
@ExcelProperty
(
"客户编码"
)
@Schema
(
description
=
"客户编码"
)
private
String
customerCode
;
/**
* 资料类型(存量、新签、续签、离职,多个用逗号分隔)
*/
@ExcelAttribute
(
name
=
"资料类型"
)
@ExcelProperty
(
"资料类型"
)
@Schema
(
description
=
"资料类型 存量、新签、续签、离职,多个用逗号分隔)"
)
private
String
materialType
;
/**
* 档案所在地-省
*/
@ExcelAttribute
(
name
=
"档案所在地-省"
)
@ExcelProperty
(
"档案所在地-省"
)
@Schema
(
description
=
"档案所在地-省"
)
private
Integer
fileProvince
;
/**
* 档案所在地-市
*/
@ExcelAttribute
(
name
=
"档案所在地-市"
)
@ExcelProperty
(
"档案所在地-市"
)
@Schema
(
description
=
"档案所在地-市"
)
private
Integer
fileCity
;
/**
* 档案所在地-县
*/
@ExcelAttribute
(
name
=
"档案所在地-县"
)
@ExcelProperty
(
"档案所在地-县"
)
@Schema
(
description
=
"档案所在地-县"
)
private
Integer
fileTown
;
/**
* 状态(0不可用,1可用)
*/
@ExcelAttribute
(
name
=
"状态"
)
@ExcelProperty
(
"状态"
)
@Schema
(
description
=
"状态(0不可用,1可用)"
)
private
String
status
;
/**
* 是否删除 0否/1是
*/
@ExcelAttribute
(
name
=
"是否删除 0否/1是"
,
maxLength
=
1
)
@Length
(
max
=
1
,
message
=
"是否删除 0否/1是不能超过1个字符"
)
@ExcelProperty
(
"是否删除 0否/1是"
)
@Schema
(
description
=
"是否删除 0否/1是"
)
private
String
deleteFlag
;
/**
* 附件Id
*/
@TableField
(
exist
=
false
)
private
List
<
String
>
attaIdList
;
/**
* 印章附件
*/
@TableField
(
exist
=
false
)
private
List
<
TAttaInfo
>
attaInfoList
;
/**
* 按任务分组的附件列表
*/
@TableField
(
exist
=
false
)
private
List
<
TaskAttachmentGroupVO
>
taskAttachmentGroups
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/entity/TElectronicArchiveTask.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
entity
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
javax.validation.constraints.NotBlank
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
@Data
@TableName
(
"t_electronic_archive_task"
)
@EqualsAndHashCode
(
callSuper
=
true
)
@Schema
(
description
=
"电子档案任务表"
)
public
class
TElectronicArchiveTask
extends
BaseEntity
{
/**
* 主键
*/
@TableId
(
type
=
IdType
.
ASSIGN_ID
)
@ExcelProperty
(
"主键"
)
@Schema
(
description
=
"主键"
)
private
String
id
;
/**
* 任务编号
*/
@ExcelAttribute
(
name
=
"任务编号"
)
@NotBlank
(
message
=
"任务编号不能为空"
)
@ExcelProperty
(
"任务编号"
)
@Schema
(
description
=
"任务编号"
)
private
String
taskCode
;
/**
* 上传表格名称
*/
@ExcelAttribute
(
name
=
"上传表格名称"
)
@ExcelProperty
(
"上传表格名称"
)
@Schema
(
description
=
"上传表格名称"
)
private
String
uploadFileName
;
/**
* 上传压缩包名称
*/
@ExcelAttribute
(
name
=
"上传压缩包名称"
)
@ExcelProperty
(
"上传压缩包名称"
)
@Schema
(
description
=
"上传压缩包名称"
)
private
String
uploadZipName
;
@Schema
(
description
=
"状态(未上传,生成电子档案中,已生成电子档案)"
)
private
String
status
;
@Schema
(
description
=
"是否删除 0否/1是"
)
private
String
deleteFlag
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/entity/TTaskArchiveRelation.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
entity
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
/**
* 电子档案上传任务和档案明细关系表
*
* @author huych
* @date 2025-12-17 11:02:01
*/
@Data
@TableName
(
"t_task_archive_relation"
)
@EqualsAndHashCode
(
callSuper
=
true
)
@Schema
(
description
=
"电子档案上传任务和档案明细关系表"
)
public
class
TTaskArchiveRelation
extends
BaseEntity
{
/**
* 主键
*/
@TableId
(
type
=
IdType
.
ASSIGN_ID
)
@ExcelProperty
(
"主键"
)
@Schema
(
description
=
"主键"
)
private
String
id
;
/**
* 任务表ID
*/
@ExcelAttribute
(
name
=
"任务表ID"
)
@ExcelProperty
(
"任务表ID"
)
@Schema
(
description
=
"任务表ID"
)
private
String
taskId
;
/**
* 电子档案明细表ID
*/
@ExcelAttribute
(
name
=
"电子档案明细表ID"
)
@ExcelProperty
(
"电子档案明细表ID"
)
@Schema
(
description
=
"电子档案明细表ID"
)
private
String
archiveDetailId
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/ArchiveBatchDownloadRequestVO.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.io.Serializable
;
/**
* 电子档案批量下载请求VO
*
* @author huych
* @date 2025-12-17
*/
@Data
@Schema
(
description
=
"电子档案批量下载请求"
)
public
class
ArchiveBatchDownloadRequestVO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 姓名
*/
@NotBlank
(
message
=
"姓名不能为空"
)
@Schema
(
description
=
"姓名"
)
private
String
empName
;
/**
* 身份证号码
*/
@NotBlank
(
message
=
"身份证号码不能为空"
)
@Schema
(
description
=
"身份证号码"
)
private
String
empIdcard
;
/**
* 项目编码
*/
@NotBlank
(
message
=
"项目编码不能为空"
)
@Schema
(
description
=
"项目编码"
)
private
String
deptNo
;
/**
* 项目名称
*/
@Schema
(
description
=
"项目名称"
)
private
String
deptName
;
/**
* 资料类型(为空则下载该人员该项目下所有资料类型)
*/
@Schema
(
description
=
"资料类型(为空则下载该人员该项目下所有资料类型)"
)
private
String
materialType
;
/**
* Excel行号(用于反馈)
*/
@Schema
(
description
=
"Excel行号"
)
private
Integer
rowIndex
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/ArchiveDownloadFeedbackVO.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serializable
;
/**
* 电子档案下载结果反馈VO
*
* @author huych
* @date 2025-12-17
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"电子档案下载结果反馈"
)
public
class
ArchiveDownloadFeedbackVO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 姓名
*/
@ExcelProperty
(
value
=
"姓名"
,
index
=
0
)
@Schema
(
description
=
"姓名"
)
private
String
empName
;
/**
* 身份证号码
*/
@ExcelProperty
(
value
=
"身份证号码"
,
index
=
1
)
@Schema
(
description
=
"身份证号码"
)
private
String
empIdcard
;
/**
* 项目编码
*/
@ExcelProperty
(
value
=
"项目编码"
,
index
=
2
)
@Schema
(
description
=
"项目编码"
)
private
String
deptNo
;
/**
* 项目名称
*/
@ExcelProperty
(
value
=
"项目名称"
,
index
=
3
)
@Schema
(
description
=
"项目名称"
)
private
String
deptName
;
/**
* 资料类型
*/
@ExcelProperty
(
value
=
"资料类型"
,
index
=
4
)
@Schema
(
description
=
"资料类型"
)
private
String
materialType
;
/**
* 下载状态(成功/失败)
*/
@ExcelProperty
(
value
=
"下载状态"
,
index
=
5
)
@Schema
(
description
=
"下载状态"
)
private
String
downloadStatus
;
/**
* 失败原因
*/
@ExcelProperty
(
value
=
"失败原因"
,
index
=
6
)
@Schema
(
description
=
"失败原因"
)
private
String
failReason
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/ArchiveFeedbackVO.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 电子档案导入反馈表VO
*
* @author huych
* @date 2025-12-17
*/
@Data
@Schema
(
description
=
"电子档案导入反馈表VO"
)
public
class
ArchiveFeedbackVO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 姓名
*/
@ExcelAttribute
(
name
=
"姓名"
)
@ExcelProperty
(
value
=
"姓名"
,
index
=
0
)
@Schema
(
description
=
"姓名"
)
private
String
empName
;
/**
* 身份证号码
*/
@ExcelAttribute
(
name
=
"身份证号码"
)
@ExcelProperty
(
value
=
"身份证号码"
,
index
=
1
)
@Schema
(
description
=
"身份证号码"
)
private
String
empIdcard
;
/**
* 项目名称
*/
@ExcelAttribute
(
name
=
"项目名称"
)
@ExcelProperty
(
value
=
"项目名称"
,
index
=
2
)
@Schema
(
description
=
"项目名称"
)
private
String
deptName
;
/**
* 项目编码
*/
@ExcelAttribute
(
name
=
"项目编码"
)
@ExcelProperty
(
value
=
"项目编码"
,
index
=
3
)
@Schema
(
description
=
"项目编码"
)
private
String
deptNo
;
/**
* 资料类型
*/
@ExcelAttribute
(
name
=
"资料类型"
)
@ExcelProperty
(
value
=
"资料类型"
,
index
=
4
)
@Schema
(
description
=
"资料类型(存量、新签、续签、离职)"
)
private
String
materialType
;
/**
* 处理结果
*/
@ExcelAttribute
(
name
=
"处理结果"
)
@ExcelProperty
(
value
=
"处理结果"
,
index
=
5
)
@Schema
(
description
=
"处理结果(成功、失败、跳过)"
)
private
String
processResult
;
/**
* 失败原因
*/
@ExcelAttribute
(
name
=
"失败原因"
)
@ExcelProperty
(
value
=
"失败原因"
,
index
=
6
)
@Schema
(
description
=
"失败原因"
)
private
String
failReason
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/ArchiveImportVO.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.RowIndex
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
javax.validation.constraints.NotBlank
;
import
java.io.Serializable
;
/**
* 电子档案导入Excel模板VO
*
* @author huych
* @date 2025-12-17
*/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
@Schema
(
description
=
"电子档案导入Excel模板VO"
)
public
class
ArchiveImportVO
extends
RowIndex
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 身份证号码
*/
@ExcelAttribute
(
name
=
"身份证号码"
,
isNotEmpty
=
true
,
errorInfo
=
"身份证号码不能为空"
,
maxLength
=
18
)
@ExcelProperty
(
value
=
"身份证号码"
,
index
=
0
)
@NotBlank
(
message
=
"身份证号码不能为空"
)
@Schema
(
description
=
"身份证号码"
)
private
String
empIdcard
;
/**
* 姓名
*/
@ExcelAttribute
(
name
=
"姓名"
,
isNotEmpty
=
true
,
errorInfo
=
"姓名不能为空"
,
maxLength
=
32
)
@ExcelProperty
(
value
=
"姓名"
,
index
=
1
)
@NotBlank
(
message
=
"姓名不能为空"
)
@Schema
(
description
=
"姓名"
)
private
String
empName
;
/**
* 项目编码
*/
@ExcelAttribute
(
name
=
"项目编码"
,
isNotEmpty
=
true
,
errorInfo
=
"项目编码不能为空"
,
maxLength
=
50
)
@ExcelProperty
(
value
=
"项目编码"
,
index
=
2
)
@NotBlank
(
message
=
"项目编码不能为空"
)
@Schema
(
description
=
"项目编码"
)
private
String
deptNo
;
/**
* 项目名称
*/
@ExcelAttribute
(
name
=
"项目名称"
,
isNotEmpty
=
true
,
errorInfo
=
"项目名称不能为空"
,
maxLength
=
50
)
@ExcelProperty
(
value
=
"项目名称"
,
index
=
3
)
@NotBlank
(
message
=
"项目名称不能为空"
)
@Schema
(
description
=
"项目名称"
)
private
String
deptName
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/TElectronicArchiveDetailSearchVo.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.time.LocalDateTime
;
import
java.util.List
;
/**
* 电子档案明细表
*
* @author huych
* @date 2025-12-17 11:03:37
*/
@Data
public
class
TElectronicArchiveDetailSearchVo
extends
TElectronicArchiveDetail
{
/**
* 多选导出或删除等操作
*/
@Schema
(
description
=
"选中ID,多个逗号分割"
)
private
String
ids
;
/**
* 创建时间区间 [开始时间,结束时间]
*/
@Schema
(
description
=
"创建时间区间"
)
private
LocalDateTime
[]
createTimes
;
/**
* @Author fxj
* 查询数据起
**/
@Schema
(
description
=
"查询limit 开始"
)
private
int
limitStart
;
/**
* @Author fxj
* 查询数据止
**/
@Schema
(
description
=
"查询limit 数据条数"
)
private
int
limitEnd
;
@Schema
(
description
=
"资料类型数组"
)
private
List
<
String
>
typeList
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/TElectronicArchiveDetailVo.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.RowIndex
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
org.hibernate.validator.constraints.Length
;
import
java.io.Serializable
;
/**
* 电子档案明细表
*
* @author huych
* @date 2025-12-17 11:03:37
*/
@Data
public
class
TElectronicArchiveDetailVo
extends
RowIndex
implements
Serializable
{
@ExcelAttribute
(
name
=
"主键"
)
@Schema
(
description
=
"主键"
)
@ExcelProperty
(
"主键"
)
private
String
id
;
@ExcelAttribute
(
name
=
"姓名"
)
@Schema
(
description
=
"姓名"
)
@ExcelProperty
(
"姓名"
)
private
String
empName
;
@ExcelAttribute
(
name
=
"身份证号码"
)
@Schema
(
description
=
"身份证号码"
)
@ExcelProperty
(
"身份证号码"
)
private
String
empIdcard
;
@ExcelAttribute
(
name
=
"项目编码"
)
@Schema
(
description
=
"项目编码"
)
@ExcelProperty
(
"项目编码"
)
private
String
deptNo
;
/**
* 项目名称
*/
@ExcelAttribute
(
name
=
"项目名称"
)
@Schema
(
description
=
"项目名称"
)
@ExcelProperty
(
"项目名称"
)
private
String
deptName
;
/**
* 客户名称
*/
@ExcelAttribute
(
name
=
"客户名称"
)
@Schema
(
description
=
"客户名称"
)
@ExcelProperty
(
"客户名称"
)
private
String
customerName
;
/**
* 客户编码
*/
@ExcelAttribute
(
name
=
"客户编码"
)
@Schema
(
description
=
"客户编码"
)
@ExcelProperty
(
"客户编码"
)
private
String
customerCode
;
/**
* 资料类型(存量、新签、续签、离职,多个用逗号分隔)
*/
@ExcelAttribute
(
name
=
"资料类型"
)
@Schema
(
description
=
"资料类型(存量、新签、续签、离职,多个用逗号分隔)"
)
@ExcelProperty
(
"资料类型"
)
private
String
materialType
;
/**
* 档案所在地-省
*/
@ExcelAttribute
(
name
=
"档案所在地-省"
)
@Schema
(
description
=
"档案所在地-省"
)
@ExcelProperty
(
"档案所在地-省"
)
private
Integer
fileProvince
;
/**
* 档案所在地-市
*/
@ExcelAttribute
(
name
=
"档案所在地-市"
)
@Schema
(
description
=
"档案所在地-市"
)
@ExcelProperty
(
"档案所在地-市"
)
private
Integer
fileCity
;
/**
* 档案所在地-县
*/
@ExcelAttribute
(
name
=
"档案所在地-县"
)
@Schema
(
description
=
"档案所在地-县"
)
@ExcelProperty
(
"档案所在地-县"
)
private
Integer
fileTown
;
/**
* 状态(0不可用,1可用)
*/
@Length
(
max
=
10
,
message
=
"状态(0不可用,1可用) 不能超过10 个字符"
)
@ExcelAttribute
(
name
=
"状态(0不可用,1可用)"
,
maxLength
=
10
)
@Schema
(
description
=
"状态(0不可用,1可用)"
)
@ExcelProperty
(
"状态(0不可用,1可用)"
)
private
String
status
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/TElectronicArchiveTaskSearchVo.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.time.LocalDateTime
;
import
java.util.List
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
@Data
public
class
TElectronicArchiveTaskSearchVo
extends
TElectronicArchiveTask
{
/**
* 多选导出或删除等操作
*/
@Schema
(
description
=
"选中ID,多个逗号分割"
)
private
String
ids
;
/**
* 创建时间区间 [开始时间,结束时间]
*/
@Schema
(
description
=
"创建时间起"
)
private
LocalDateTime
createTimeStart
;
/**
* 创建时间区间 [开始时间,结束时间]
*/
@Schema
(
description
=
"创建时间止"
)
private
LocalDateTime
createTimeEnd
;
/**
* @Author fxj
* 查询数据起
**/
@Schema
(
description
=
"查询limit 开始"
)
private
int
limitStart
;
/**
* @Author fxj
* 查询数据止
**/
@Schema
(
description
=
"查询limit 数据条数"
)
private
int
limitEnd
;
@Schema
(
description
=
"资料类型数组"
)
private
List
<
String
>
typeList
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/TElectronicArchiveTaskVo.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.RowIndex
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
@Data
public
class
TElectronicArchiveTaskVo
extends
RowIndex
implements
Serializable
{
@ExcelAttribute
(
name
=
"主键"
)
@Schema
(
description
=
"主键"
)
@ExcelProperty
(
"主键"
)
private
String
id
;
@ExcelAttribute
(
name
=
"任务编号"
)
@Schema
(
description
=
"任务编号"
)
@ExcelProperty
(
"任务编号"
)
private
String
taskCode
;
@ExcelAttribute
(
name
=
"上传表格名称"
)
@Schema
(
description
=
"上传表格名称"
)
@ExcelProperty
(
"上传表格名称"
)
private
String
uploadFileName
;
@ExcelAttribute
(
name
=
"上传压缩包名称"
)
@Schema
(
description
=
"上传压缩包名称"
)
@ExcelProperty
(
"上传压缩包名称"
)
private
String
uploadZipName
;
@ExcelAttribute
(
name
=
"状态"
)
@Schema
(
description
=
"状态(未上传,生成电子档案中,已生成电子档案)"
)
@ExcelProperty
(
"状态"
)
private
String
status
;
}
yifu-batch/yifu-batch-api/src/main/java/com/yifu/cloud/plus/v1/batch/vo/TaskAttachmentGroupVO.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
vo
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.time.LocalDateTime
;
import
java.util.List
;
import
java.util.Map
;
/**
* 任务附件分组VO
* 用于按任务分组展示电子档案的附件信息
*
* @author huych
* @date 2025-12-17
*/
@Data
@Schema
(
description
=
"任务附件分组VO"
)
public
class
TaskAttachmentGroupVO
{
/**
* 任务ID
*/
@Schema
(
description
=
"任务ID"
)
private
String
taskId
;
/**
* 任务编号
*/
@Schema
(
description
=
"任务编号"
)
private
String
taskCode
;
/**
* 上传人
*/
@Schema
(
description
=
"上传人"
)
private
String
createUser
;
/**
* 上传时间
*/
@Schema
(
description
=
"上传时间"
)
private
LocalDateTime
createTime
;
/**
* 资料类型及对应的附件列表
* key: 资料类型(存量、新签、续签、离职)
* value: 该资料类型下的附件列表
*/
@Schema
(
description
=
"资料类型及对应的附件列表"
)
private
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeAttachments
;
}
yifu-batch/yifu-batch-biz/pom.xml
View file @
3ffe3bb0
...
...
@@ -85,30 +85,19 @@
<artifactId>
jsch
</artifactId>
<version>
0.1.55
</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.shardingsphere</groupId>-->
<!-- <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>-->
<!-- <version>5.1.2</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.shardingsphere</groupId>-->
<!-- <artifactId>sharding-transaction-base-seata-at</artifactId>-->
<!-- <version>4.1.1</version>-->
<!-- </dependency>-->
<dependency>
<groupId>
com.yifu.cloud.plus.v1
</groupId>
<artifactId>
yifu-common-core
</artifactId>
</dependency>
<dependency>
<groupId>
com.yifu.cloud.plus.v1
</groupId>
<artifactId>
yifu-common-batch
</artifactId>
<version>
1.0.0
</version>
</dependency>
<dependency>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-cp
</artifactId>
<version>
4.7.0
</version>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-test
</artifactId>
</dependency>
</dependencies>
<build>
...
...
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/controller/FileUploadController.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
controller
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.yifu.cloud.plus.v1.batch.service.FileUploadService
;
import
com.yifu.cloud.plus.v1.batch.service.TAttaInfoService
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.OSSUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.log.annotation.SysLog
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.poi.ss.formula.functions.T
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.util.List
;
/**
* @author fang
* 文件上传接口
*/
@RestController
@RequestMapping
(
"/fileUpload"
)
@Tag
(
name
=
"文件上传接口"
)
@Slf4j
public
class
FileUploadController
{
@Autowired
private
OSSUtil
ossUtil
;
@Autowired
private
TAttaInfoService
tAttaInfoService
;
@Autowired
private
FileUploadService
fileUploadService
;
/**
* @Author fxj
* @Description
* @Date 13:49 2022/6/17
* @Param
* @return
**/
@Operation
(
description
=
"OSS文件上传接口"
+
"@ApiImplicitParam(name = \"file\", value = \"Form文件上传\", required = true, dataType = \"__file\", paramType = \"form\"),\n"
+
"\t\t\t@ApiImplicitParam(name = \"filePath\", value = \"文件上传路径\", required = false, dataType = \"String\", paramType = \"form\"),\n"
+
"\t\t\t@ApiImplicitParam(name = \"type\", value = \"关系类型 1 任务表附件 2 zip附件 3反馈表附件\", required = true, dataType = \"int\", paramType = \"form\"),\n"
+
"\t\t\t@ApiImplicitParam(name = \"domain\", value = \"实体id(传入就插入对应关系,用于编辑)\", required = false, paramType = \"form\")\n"
+
"\t"
)
@PostMapping
(
value
=
"/ossUploadFile"
)
public
R
<
T
>
uploadImg
(
@RequestBody
MultipartFile
file
,
String
filePath
,
String
type
,
String
domain
)
throws
IOException
{
return
fileUploadService
.
uploadAsso
(
file
,
filePath
,
type
,
domain
,
CommonConstants
.
ZERO_STRING
);
}
/**
* @Author hgw
* @Description 改编自ossUploadFile接口,改变了回传信息——专为预入职微信端使用——忽略了token,其余人慎用
* @Date 13:49 2022/6/17
* @Param relationTypeSub 预入职其他附件的子类型
* @return
**/
@Operation
(
description
=
"OSS文件上传接口"
+
"@ApiImplicitParam(name = \"file\", value = \"Form文件上传\", required = true, dataType = \"__file\", paramType = \"form\"),\n"
+
"\t\t\t@ApiImplicitParam(name = \"filePath\", value = \"文件上传路径\", required = false, dataType = \"String\", paramType = \"form\"),\n"
+
"\t\t\t@ApiImplicitParam(name = \"type\", value = \"关系类型 1 任务表附件 2 zip附件 3反馈表附件\", required = true, dataType = \"int\", paramType = \"form\"),\n"
+
"\t\t\t@ApiImplicitParam(name = \"domain\", value = \"实体id(传入就插入对应关系,用于编辑)\", required = false, paramType = \"form\")\n"
+
"\t"
)
@PostMapping
(
value
=
"/uploadFileReturnAtta"
)
public
R
<
T
>
uploadFileReturnAtta
(
@RequestBody
MultipartFile
file
,
String
filePath
,
String
type
,
String
domainId
)
throws
IOException
{
return
fileUploadService
.
uploadAsso
(
file
,
filePath
,
type
,
domainId
,
CommonConstants
.
ONE_STRING
);
}
/**
* @Author fxj
* @Description
* @Date 13:51 2022/6/17
* @Param
* @return
**/
@Operation
(
description
=
"附件删除"
)
@SysLog
(
"附件删除"
)
@PostMapping
(
"/ossFileDelete/deleteByIds"
)
public
R
<
Boolean
>
ossFileDelete
(
@RequestBody
List
<
String
>
Ids
)
{
if
(
Common
.
isNotNull
(
Ids
))
{
try
{
for
(
String
id
:
Ids
)
{
TAttaInfo
attaInfo
=
tAttaInfoService
.
getById
(
id
);
if
(
null
==
attaInfo
)
{
return
R
.
failed
(
"无对应附件信息"
);
}
if
(
tAttaInfoService
.
removeById
(
id
))
{
ossUtil
.
deleteObject
(
null
,
attaInfo
.
getAttaSrc
());
return
R
.
ok
(
null
,
"删除成功!"
);
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"附件删除异常:"
+
e
.
getMessage
());
return
R
.
failed
(
"附件删除异常!"
);
}
}
return
R
.
ok
(
null
,
"删除失败!"
);
}
/**
* 获取附件下载地址
*
* @param id
* @return
* @Author fxj
* @Date 2019-08-16
* @param id domainId
**/
@Operation
(
description
=
"附件预览下载地址 资源类型 0 存量 1 新签 2续签 3离职"
)
@GetMapping
(
"/ossFileUrl/{id}"
)
public
R
<
List
<
TAttaInfo
>>
ossFileUrl
(
@PathVariable
String
id
)
{
List
<
TAttaInfo
>
attas
=
tAttaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
query
().
lambda
().
eq
(
TAttaInfo:
:
getDomainId
,
id
));
if
(
Common
.
isEmpty
(
attas
))
{
return
new
R
<>(
attas
);
}
for
(
TAttaInfo
atta:
attas
){
URL
url
=
ossUtil
.
getObjectUrl
(
null
,
atta
.
getAttaSrc
());
atta
.
setAttaUrl
(
url
.
toString
().
replace
(
"http"
,
"https"
));
}
return
new
R
<>(
attas
);
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/controller/TElectronicArchiveTaskController.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
controller
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
com.yifu.cloud.plus.v1.batch.service.ElectronicArchiveImportService
;
import
com.yifu.cloud.plus.v1.batch.service.TElectronicArchiveTaskService
;
import
com.yifu.cloud.plus.v1.batch.vo.TElectronicArchiveTaskSearchVo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Parameter
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
@RestController
@RequiredArgsConstructor
@RequestMapping
(
"/telectronicarchivetask"
)
@Tag
(
name
=
"电子档案任务表管理"
)
public
class
TElectronicArchiveTaskController
{
private
final
TElectronicArchiveTaskService
tElectronicArchiveTaskService
;
private
final
ElectronicArchiveImportService
importService
;
/**
* 简单分页查询
*
* @param page 分页对象
* @param tElectronicArchiveTask 电子档案任务表
* @return
*/
@Operation
(
description
=
"简单分页查询"
)
@GetMapping
(
"/page"
)
public
R
<
IPage
<
TElectronicArchiveTask
>>
getTElectronicArchiveTaskPage
(
Page
<
TElectronicArchiveTask
>
page
,
TElectronicArchiveTaskSearchVo
tElectronicArchiveTask
)
{
return
new
R
<>(
tElectronicArchiveTaskService
.
getTElectronicArchiveTaskPage
(
page
,
tElectronicArchiveTask
));
}
/**
* 通过id查询电子档案任务表
*
* @param id id
* @return R
*/
@Operation
(
summary
=
"通过id查询"
,
description
=
"通过id查询"
)
@GetMapping
(
"/{id}"
)
public
R
<
TElectronicArchiveTask
>
getById
(
@PathVariable
(
"id"
)
String
id
)
{
return
R
.
ok
(
tElectronicArchiveTaskService
.
getById
(
id
));
}
/**
* 通过id删除电子档案任务表
*
* @param id id
* @return R
*/
@Operation
(
summary
=
"通过id删除"
,
description
=
"通过id删除"
)
@PostMapping
(
"/deleteById"
)
public
R
<?>
deleteById
(
@RequestParam
String
id
)
{
return
tElectronicArchiveTaskService
.
deleteTaskById
(
id
);
}
/**
* 第一步:导入Excel模板文件
*
* @param file Excel文件
* @return R
*/
@Operation
(
summary
=
"导入Excel模板文件"
,
description
=
"第一步:导入Excel模板文件,包含身份证、姓名、项目编码、项目名称"
)
@PostMapping
(
"/importExcel"
)
public
R
<?>
importExcel
(
@Parameter
(
description
=
"Excel文件"
)
@RequestParam
(
"file"
)
MultipartFile
file
)
{
if
(
file
==
null
||
file
.
isEmpty
())
{
return
R
.
failed
(
"文件不能为空"
);
}
String
fileName
=
file
.
getOriginalFilename
();
if
(
fileName
==
null
||
!
fileName
.
toLowerCase
().
endsWith
(
".xlsx"
)
&&
!
fileName
.
toLowerCase
().
endsWith
(
".xls"
))
{
return
R
.
failed
(
"文件格式不正确,请上传Excel文件"
);
}
try
{
return
importService
.
importExcelTemplate
(
file
.
getInputStream
(),
fileName
);
}
catch
(
IOException
e
)
{
return
R
.
failed
(
"文件读取失败:"
+
e
.
getMessage
());
}
}
/**
* 第二步:导入ZIP文件
*
* @param file ZIP文件
* @param taskId 任务ID
* @return R
*/
@Operation
(
summary
=
"导入ZIP文件"
,
description
=
"第二步:导入ZIP文件,包含员工档案资料"
)
@PostMapping
(
"/importZip"
)
public
R
<?>
importZip
(
@Parameter
(
description
=
"ZIP文件"
)
@RequestParam
(
"file"
)
MultipartFile
file
,
@Parameter
(
description
=
"任务ID"
)
@RequestParam
(
"taskId"
)
String
taskId
)
{
if
(
file
==
null
||
file
.
isEmpty
())
{
return
R
.
failed
(
"文件不能为空"
);
}
String
fileName
=
file
.
getOriginalFilename
();
if
(
fileName
==
null
||
!
fileName
.
toLowerCase
().
endsWith
(
".zip"
))
{
return
R
.
failed
(
"文件格式不正确,请上传ZIP文件"
);
}
return
importService
.
importZipFile
(
file
,
taskId
);
}
/**
* 查询任务状态
*
* @param taskId 任务ID
* @return R
*/
@Operation
(
summary
=
"查询任务状态"
,
description
=
"查询电子档案导入任务的处理状态"
)
@GetMapping
(
"/status/{taskId}"
)
public
R
<
TElectronicArchiveTask
>
getTaskStatus
(
@PathVariable
(
"taskId"
)
String
taskId
)
{
TElectronicArchiveTask
task
=
tElectronicArchiveTaskService
.
getById
(
taskId
);
if
(
task
==
null
)
{
return
R
.
failed
(
"任务不存在"
);
}
return
R
.
ok
(
task
);
}
/**
* 手动触发异步处理(用于重试)
*
* @param taskId 任务ID
* @return R
*/
@Operation
(
summary
=
"手动触发异步处理"
,
description
=
"手动触发异步处理任务(用于重试失败的任务)"
)
@PostMapping
(
"/retryProcess/{taskId}"
)
public
R
<?>
retryProcess
(
@PathVariable
(
"taskId"
)
String
taskId
)
{
TElectronicArchiveTask
task
=
tElectronicArchiveTaskService
.
getById
(
taskId
);
if
(
task
==
null
)
{
return
R
.
failed
(
"任务不存在"
);
}
// 只有生成中或失败的任务才能重试
// 这里可以根据需要增加失败状态
return
importService
.
asyncProcessUpload
(
taskId
);
}
/**
* 单个新增人员附件
*
* @param detail 人员信息
* @param files 附件文件列表
* @return R
*/
@Operation
(
summary
=
"单个新增人员附件"
,
description
=
"单个新增人员档案附件,包含身份证号、姓名、项目编码、项目名称、资料类型和多个附件"
)
@PostMapping
(
"/uploadSingleArchive"
)
public
R
<?>
uploadSingleArchive
(
@RequestBody
TElectronicArchiveDetail
detail
,
@RequestParam
(
"files"
)
MultipartFile
[]
files
)
{
// 参数校验
if
(
files
==
null
||
files
.
length
==
0
)
{
return
R
.
failed
(
"附件不能为空"
);
}
return
importService
.
uploadSinglePersonArchive
(
detail
.
getEmpIdcard
(),
detail
.
getEmpName
()
,
detail
.
getDeptNo
(),
detail
.
getDeptName
(),
detail
.
getMaterialType
(),
files
);
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/controller/TTaskArchiveRelationController.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
controller
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
import
com.yifu.cloud.plus.v1.batch.service.TTaskArchiveRelationService
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* 电子档案上传任务和档案明细关系表
*
* @author huych
* @date 2025-12-17 11:02:01
*/
@RestController
@RequiredArgsConstructor
@RequestMapping
(
"/ttaskarchiverelation"
)
@Tag
(
name
=
"电子档案上传任务和档案明细关系表管理"
)
public
class
TTaskArchiveRelationController
{
private
final
TTaskArchiveRelationService
tTaskArchiveRelationService
;
/**
* 简单分页查询
* @param page 分页对象
* @param tTaskArchiveRelation 电子档案上传任务和档案明细关系表
* @return
*/
@Operation
(
description
=
"简单分页查询"
)
@GetMapping
(
"/page"
)
public
R
<
IPage
<
TTaskArchiveRelation
>>
getTTaskArchiveRelationPage
(
Page
<
TTaskArchiveRelation
>
page
,
TTaskArchiveRelation
tTaskArchiveRelation
)
{
return
new
R
<>(
tTaskArchiveRelationService
.
getTTaskArchiveRelationPage
(
page
,
tTaskArchiveRelation
));
}
/**
* 通过id查询电子档案上传任务和档案明细关系表
* @param id id
* @return R
*/
@Operation
(
summary
=
"通过id查询"
,
description
=
"通过id查询"
)
@GetMapping
(
"/{id}"
)
public
R
<
TTaskArchiveRelation
>
getById
(
@PathVariable
(
"id"
)
String
id
)
{
return
R
.
ok
(
tTaskArchiveRelationService
.
getById
(
id
));
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/mapper/SysConfigLimitMapper.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.yifu.cloud.plus.v1.batch.entity.SysConfigLimit
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
/**
* 系统限制配置表
*
* @author hgw
* @date 2024-09-24 17:39:57
*/
@Mapper
public
interface
SysConfigLimitMapper
extends
BaseMapper
<
SysConfigLimit
>
{
/**
* 系统限制配置表简单分页查询
*
* @param configKey 键
* @return
*/
Integer
getSysConfigLimitByKey
(
@Param
(
"configKey"
)
String
configKey
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/mapper/TAttaInfoMapper.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.time.LocalDateTime
;
import
java.util.Collection
;
import
java.util.List
;
/**
* 附件信息表
*
* @author pwang
* @date 2021-02-19 16:16:07
*/
@Mapper
public
interface
TAttaInfoMapper
extends
BaseMapper
<
TAttaInfo
>
{
/**
* 附件信息表简单分页查询
*
* @param tAttaInfo 附件信息表
* @return
*/
IPage
<
TAttaInfo
>
getTAttaInfoPage
(
Page
<
TAttaInfo
>
page
,
@Param
(
"tAttaInfo"
)
TAttaInfo
tAttaInfo
);
/**
* @param tAttaInfo
* @Description: 获取list
* @Author: hgw
* @Date: 2021/5/28 16:02
* @return: java.util.List<com.yifu.cloud.v1.crm.api.entity.TAttaInfo>
**/
List
<
TAttaInfo
>
getTAttaInfoList
(
@Param
(
"tAttaInfo"
)
TAttaInfo
tAttaInfo
);
List
<
TAttaInfo
>
getTAttaInfoListByDoMainId
(
@Param
(
"domainId"
)
String
domainId
);
int
updateDomainId
(
@Param
(
"domainId"
)
String
domainId
,
@Param
(
"ids"
)
List
<
String
>
ids
);
List
<
TAttaInfo
>
getAttaByApplyId
(
@Param
(
"applyId"
)
String
applyId
);
void
deleteByDomainId
(
@Param
(
"domainId"
)
String
domainId
);
void
deleteByDomainIdAndType
(
@Param
(
"domainId"
)
String
domainId
,
@Param
(
"relationType"
)
String
relationType
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/mapper/TElectronicArchiveDetailMapper.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
com.yifu.cloud.plus.v1.batch.vo.TElectronicArchiveDetailSearchVo
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
/**
* 电子档案明细表
*
* @author huych
* @date 2025-12-17 11:03:37
*/
@Mapper
public
interface
TElectronicArchiveDetailMapper
extends
BaseMapper
<
TElectronicArchiveDetail
>
{
/**
* 电子档案明细表简单分页查询
* @param tElectronicArchiveDetail 电子档案明细表
* @return
*/
IPage
<
TElectronicArchiveDetail
>
getTElectronicArchiveDetailPage
(
Page
<
TElectronicArchiveDetail
>
page
,
@Param
(
"tElectronicArchiveDetail"
)
TElectronicArchiveDetailSearchVo
tElectronicArchiveDetail
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/mapper/TElectronicArchiveTaskMapper.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
com.yifu.cloud.plus.v1.batch.vo.TElectronicArchiveTaskSearchVo
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
@Mapper
public
interface
TElectronicArchiveTaskMapper
extends
BaseMapper
<
TElectronicArchiveTask
>
{
/**
* 电子档案任务表简单分页查询
* @param tElectronicArchiveTask 电子档案任务表
* @return
*/
IPage
<
TElectronicArchiveTask
>
getTElectronicArchiveTaskPage
(
Page
<
TElectronicArchiveTask
>
page
,
@Param
(
"tElectronicArchiveTask"
)
TElectronicArchiveTaskSearchVo
tElectronicArchiveTask
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/mapper/TTaskArchiveRelationMapper.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
/**
* 电子档案上传任务和档案明细关系表
*
* @author huych
* @date 2025-12-17 11:02:01
*/
@Mapper
public
interface
TTaskArchiveRelationMapper
extends
BaseMapper
<
TTaskArchiveRelation
>
{
/**
* 电子档案上传任务和档案明细关系表简单分页查询
* @param tTaskArchiveRelation 电子档案上传任务和档案明细关系表
* @return
*/
IPage
<
TTaskArchiveRelation
>
getTTaskArchiveRelationPage
(
Page
<
TTaskArchiveRelation
>
page
,
@Param
(
"tTaskArchiveRelation"
)
TTaskArchiveRelation
tTaskArchiveRelation
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/ElectronicArchiveImportService.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.InputStream
;
/**
* 电子档案导入服务接口
*
* @author huych
* @date 2025-12-17
*/
public
interface
ElectronicArchiveImportService
{
/**
* 第一步:导入Excel模板文件
*
* @param inputStream Excel文件流
* @param fileName 文件名
* @return 导入结果
*/
R
<?>
importExcelTemplate
(
InputStream
inputStream
,
String
fileName
);
/**
* 第二步:导入ZIP文件
*
* @param file ZIP文件
* @param taskId 任务ID
* @return 导入结果
*/
R
<?>
importZipFile
(
MultipartFile
file
,
String
taskId
);
/**
* 第三步:异步处理上传
*
* @param taskId 任务ID
* @return 处理结果
*/
R
<?>
asyncProcessUpload
(
String
taskId
);
/**
* 生成任务编号
*
* @return 任务编号
*/
String
generateTaskCode
();
/**
* 单个新增人员附件
*
* @param empIdcard 身份证号
* @param empName 姓名
* @param deptNo 项目编码
* @param deptName 项目名称
* @param materialType 资料类型
* @param files 附件文件列表
* @return 上传结果
*/
R
<?>
uploadSinglePersonArchive
(
String
empIdcard
,
String
empName
,
String
deptNo
,
String
deptName
,
String
materialType
,
MultipartFile
[]
files
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/FileUploadService.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.FileVo
;
import
org.apache.poi.ss.formula.functions.T
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
/**
* 文件上传
*
* @author pwang
* @date 2022-07-27 16:16:07
*/
public
interface
FileUploadService
{
R
<
FileVo
>
uploadImg
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domain
)
throws
IOException
;
R
<
TAttaInfo
>
uploadFileReturnAtta
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domainId
)
throws
IOException
;
R
<
T
>
uploadAsso
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domain
,
String
uploadType
);
/**
* 检查文件是否存在
*
* @param filePath 文件路径
* @return 是否存在
*/
boolean
checkFileExists
(
String
filePath
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/TAttaInfoService.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
java.util.List
;
/**
* 附件信息表
*
* @author pwang
* @date 2021-02-19 16:16:07
*/
public
interface
TAttaInfoService
extends
IService
<
TAttaInfo
>
{
/**
* @param domainId 关联id
* @Description: 根据domainId获取附件
* @Author: huych
* @Date: 2025/12/17 18:23
* @return: java.util.List<com.yifu.cloud.plus.v1.yifu.archives.entity.TAttaInfo>
**/
List
<
TAttaInfo
>
getTAttaInfoListByDoMainId
(
String
domainId
);
Boolean
updateDomainId
(
String
domainId
,
List
<
String
>
ids
);
/**
* @param applyId
* @Description: 收入证明使用
* @Author: hgw
* @Date: 2023/2/22 10:50
* @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.util.List < com.yifu.cloud.plus.v1.yifu.archives.entity.TAttaInfo>>
**/
R
<
List
<
TAttaInfo
>>
getAttaByApplyId
(
String
applyId
);
/**
* @param domainId 关联id
* @Description: 删除附件
* @Author: hgw
* @Date: 2024/6/20 14:50
* @return: void
**/
void
deleteByDomainId
(
String
domainId
);
TAttaInfo
add
(
TAttaInfo
attaInfo
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/TElectronicArchiveDetailService.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
com.yifu.cloud.plus.v1.batch.vo.ArchiveAttachmentDeleteRequestVO
;
import
com.yifu.cloud.plus.v1.batch.vo.ArchiveBatchDownloadRequestVO
;
import
com.yifu.cloud.plus.v1.batch.vo.ArchiveSelectedExportRequestVO
;
import
com.yifu.cloud.plus.v1.batch.vo.TElectronicArchiveDetailSearchVo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
javax.servlet.http.HttpServletResponse
;
import
java.util.List
;
/**
* 电子档案明细表
*
* @author huych
* @date 2025-12-17 11:03:37
*/
public
interface
TElectronicArchiveDetailService
extends
IService
<
TElectronicArchiveDetail
>
{
/**
* 电子档案明细表简单分页查询
* @param tElectronicArchiveDetail 电子档案明细表
* @return
*/
IPage
<
TElectronicArchiveDetail
>
getTElectronicArchiveDetailPage
(
Page
<
TElectronicArchiveDetail
>
page
,
TElectronicArchiveDetailSearchVo
tElectronicArchiveDetail
);
/**
* 通过id查询电子档案明细表
* @param id id
* @return
*/
R
<
TElectronicArchiveDetail
>
getDetailInfoById
(
String
id
);
/**
* 批量下载电子档案
* @param requestList 下载请求列表
* @param response HTTP响应
*/
void
batchDownloadArchives
(
List
<
ArchiveBatchDownloadRequestVO
>
requestList
,
HttpServletResponse
response
);
/**
* 删除电子档案附件
* @param request 删除请求
* @return 删除结果
*/
R
<
String
>
deleteArchiveAttachments
(
ArchiveAttachmentDeleteRequestVO
request
);
/**
* 勾选导出电子档案
* @param requestList 导出请求列表
* @param response HTTP响应
*/
void
selectedExportArchives
(
List
<
ArchiveSelectedExportRequestVO
>
requestList
,
HttpServletResponse
response
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/TElectronicArchiveTaskService.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
com.yifu.cloud.plus.v1.batch.vo.TElectronicArchiveTaskSearchVo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
public
interface
TElectronicArchiveTaskService
extends
IService
<
TElectronicArchiveTask
>
{
/**
* 电子档案任务表简单分页查询
* @param tElectronicArchiveTask 电子档案任务表
* @return
*/
IPage
<
TElectronicArchiveTask
>
getTElectronicArchiveTaskPage
(
Page
<
TElectronicArchiveTask
>
page
,
TElectronicArchiveTaskSearchVo
tElectronicArchiveTask
);
R
deleteTaskById
(
String
id
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/TTaskArchiveRelationService.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
/**
* 电子档案上传任务和档案明细关系表
*
* @author huych
* @date 2025-12-17 11:02:01
*/
public
interface
TTaskArchiveRelationService
extends
IService
<
TTaskArchiveRelation
>
{
/**
* 电子档案上传任务和档案明细关系表简单分页查询
* @param tTaskArchiveRelation 电子档案上传任务和档案明细关系表
* @return
*/
IPage
<
TTaskArchiveRelation
>
getTTaskArchiveRelationPage
(
Page
<
TTaskArchiveRelation
>
page
,
TTaskArchiveRelation
tTaskArchiveRelation
);
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/ElectronicArchiveImportServiceImpl.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
.
impl
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.alibaba.excel.EasyExcel
;
import
com.alibaba.excel.context.AnalysisContext
;
import
com.alibaba.excel.read.listener.ReadListener
;
import
com.alibaba.excel.read.metadata.holder.ReadRowHolder
;
import
com.alibaba.excel.util.ListUtils
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.yifu.cloud.plus.v1.batch.constants.ArchiveConstants
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
import
com.yifu.cloud.plus.v1.batch.service.*
;
import
com.yifu.cloud.plus.v1.batch.vo.ArchiveFeedbackVO
;
import
com.yifu.cloud.plus.v1.batch.vo.ArchiveImportVO
;
import
com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeInfo
;
import
com.yifu.cloud.plus.v1.yifu.archives.vo.IdNameNoVo
;
import
com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainSelectVo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.*
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.log4j.Log4j2
;
import
org.springframework.cache.Cache
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.cache.support.SimpleValueWrapper
;
import
org.springframework.mock.web.MockMultipartFile
;
import
org.springframework.scheduling.annotation.Async
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.InputStream
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 电子档案导入服务实现
*
* @author huych
* @date 2025-12-17
*/
@Log4j2
@Service
@RequiredArgsConstructor
public
class
ElectronicArchiveImportServiceImpl
implements
ElectronicArchiveImportService
{
private
final
TElectronicArchiveTaskService
taskService
;
private
final
TElectronicArchiveDetailService
detailService
;
private
final
TTaskArchiveRelationService
relationService
;
private
final
TAttaInfoService
attaInfoService
;
private
final
FileUploadService
fileUploadService
;
private
final
ArchivesDaprUtil
archivesDaprUtil
;
private
final
CacheManager
cacheManager
;
/**
* 第一步:导入Excel模板文件
*/
@Override
public
R
<?>
importExcelTemplate
(
InputStream
inputStream
,
String
fileName
)
{
YifuUser
user
=
SecurityUtils
.
getUser
();
if
(
null
==
user
)
{
return
R
.
failed
(
"用户未登录"
);
}
// 成功导入的数据
List
<
ArchiveImportVO
>
successList
=
new
ArrayList
<>();
ExcelUtil
<
ArchiveImportVO
>
util
=
new
ExcelUtil
<>(
ArchiveImportVO
.
class
);
List
<
ErrorMessage
<
ArchiveImportVO
>>
errorMessageList
=
new
ArrayList
<>();
try
{
EasyExcel
.
read
(
inputStream
,
ArchiveImportVO
.
class
,
new
ReadListener
<
ArchiveImportVO
>()
{
public
static
final
int
BATCH_COUNT
=
CommonConstants
.
BATCH_COUNT
;
private
List
<
ArchiveImportVO
>
cachedDataList
=
ListUtils
.
newArrayListWithExpectedSize
(
BATCH_COUNT
);
@Override
public
void
invoke
(
ArchiveImportVO
data
,
AnalysisContext
context
)
{
ReadRowHolder
readRowHolder
=
context
.
readRowHolder
();
Integer
rowIndex
=
readRowHolder
.
getRowIndex
();
data
.
setRowIndex
(
rowIndex
+
1
);
ErrorMessage
<
ArchiveImportVO
>
errorMessage
=
util
.
checkEntity
(
data
,
data
.
getRowIndex
());
if
(
Common
.
isNotNull
(
errorMessage
))
{
errorMessageList
.
add
(
errorMessage
);
}
else
{
cachedDataList
.
add
(
data
);
}
if
(
cachedDataList
.
size
()
>=
BATCH_COUNT
)
{
saveData
();
cachedDataList
=
ListUtils
.
newArrayListWithExpectedSize
(
BATCH_COUNT
);
}
}
@Override
public
void
doAfterAllAnalysed
(
AnalysisContext
context
)
{
saveData
();
}
private
void
saveData
()
{
if
(
CollUtil
.
isNotEmpty
(
cachedDataList
))
{
processImportData
(
cachedDataList
,
errorMessageList
,
successList
,
user
);
}
}
}).
sheet
().
doRead
();
// 如果校验失败,返回错误信息
if
(
CollUtil
.
isNotEmpty
(
errorMessageList
))
{
return
R
.
failed
(
errorMessageList
);
}
// 校验通过,生成任务表数据
if
(
CollUtil
.
isEmpty
(
successList
))
{
return
R
.
failed
(
"没有有效的数据可以导入"
);
}
// 生成任务编号
String
taskCode
=
generateTaskCode
();
// 创建任务
TElectronicArchiveTask
task
=
new
TElectronicArchiveTask
();
task
.
setTaskCode
(
taskCode
);
task
.
setUploadFileName
(
fileName
);
task
.
setStatus
(
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
task
.
setDeleteFlag
(
CommonConstants
.
ZERO_STRING
);
taskService
.
save
(
task
);
// 保存任务表附件
saveTaskAttachment
(
task
.
getId
(),
fileName
,
inputStream
,
user
);
// 建立任务和档案详情的关联关系
createTaskArchiveRelations
(
task
.
getId
(),
successList
);
return
R
.
ok
(
"导入成功,任务编号:"
+
taskCode
);
}
catch
(
Exception
e
)
{
log
.
error
(
"导入Excel文件失败"
,
e
);
return
R
.
failed
(
"导入失败:"
+
e
.
getMessage
());
}
}
/**
* 处理导入数据
*/
private
void
processImportData
(
List
<
ArchiveImportVO
>
dataList
,
List
<
ErrorMessage
<
ArchiveImportVO
>>
errorMessageList
,
List
<
ArchiveImportVO
>
successList
,
YifuUser
user
)
{
TEmployeeInfo
empInfo
;
TSettleDomainSelectVo
settleResult
;
R
<
TEmployeeInfo
>
empResult
;
Map
<
String
,
String
>
map
=
new
HashMap
<>();
for
(
ArchiveImportVO
data
:
dataList
)
{
try
{
// 1. 校验表格中一个姓名、身份证只能有一条
String
uniqueKey
=
data
.
getEmpIdcard
()
+
"_"
+
data
.
getEmpName
()
+
"_"
+
data
.
getDeptNo
();
if
(
null
!=
map
.
get
(
uniqueKey
))
{
ErrorMessage
<
ArchiveImportVO
>
errorMessage
=
new
ErrorMessage
<>(
data
.
getRowIndex
()
,
"第"
+
data
.
getRowIndex
()
+
"行:姓名和身份证信息存在重复数据"
,
data
);
errorMessageList
.
add
(
errorMessage
);
continue
;
}
else
{
map
.
put
(
uniqueKey
,
"1"
);
}
// 查询项目信息获取客户信息
settleResult
=
archivesDaprUtil
.
selectDeptByNo
(
data
.
getDeptNo
());
if
(
settleResult
==
null
)
{
ErrorMessage
<
ArchiveImportVO
>
errorMessage
=
new
ErrorMessage
<>(
data
.
getRowIndex
()
,
"第"
+
data
.
getRowIndex
()
+
"行:项目编码["
+
data
.
getDeptNo
()
+
"]信息不存在"
,
data
);
errorMessageList
.
add
(
errorMessage
);
continue
;
}
// 查询人员档案信息获取档案所在地
IdNameNoVo
vo
=
new
IdNameNoVo
();
vo
.
setName
(
data
.
getEmpName
());
vo
.
setNo
(
data
.
getEmpIdcard
());
empResult
=
archivesDaprUtil
.
getTEmployeeInfoByIdcardAndName
(
vo
);
if
(
empResult
==
null
||
empResult
.
getData
()
==
null
)
{
ErrorMessage
<
ArchiveImportVO
>
errorMessage
=
new
ErrorMessage
<>(
data
.
getRowIndex
()
,
"第"
+
data
.
getRowIndex
()
+
"行:人员档案信息不存在"
,
data
);
errorMessageList
.
add
(
errorMessage
);
continue
;
}
empInfo
=
empResult
.
getData
();
// 查找是否存在相同的电子档案明细
LambdaQueryWrapper
<
TElectronicArchiveDetail
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
TElectronicArchiveDetail:
:
getEmpIdcard
,
data
.
getEmpIdcard
())
.
eq
(
TElectronicArchiveDetail:
:
getEmpName
,
data
.
getEmpName
())
.
eq
(
TElectronicArchiveDetail:
:
getDeptNo
,
data
.
getDeptNo
())
.
eq
(
TElectronicArchiveDetail:
:
getDeleteFlag
,
CommonConstants
.
ZERO_STRING
)
.
last
(
CommonConstants
.
LAST_ONE_SQL
);
TElectronicArchiveDetail
existDetail
=
detailService
.
getOne
(
wrapper
);
if
(
existDetail
==
null
)
{
// 不存在,生成新的明细数据
TElectronicArchiveDetail
detail
=
new
TElectronicArchiveDetail
();
detail
.
setEmpName
(
data
.
getEmpName
());
detail
.
setEmpIdcard
(
data
.
getEmpIdcard
());
detail
.
setDeptNo
(
data
.
getDeptNo
());
detail
.
setDeptName
(
data
.
getDeptName
());
detail
.
setCustomerName
(
settleResult
.
getCustomerName
());
detail
.
setCustomerCode
(
settleResult
.
getCustomerCode
());
detail
.
setMaterialType
(
""
);
// 初始为空,第三步处理时填充
detail
.
setStatus
(
ArchiveConstants
.
DETAIL_STATUS_DISABLED
);
detail
.
setDeleteFlag
(
CommonConstants
.
ZERO_STRING
);
// 设置档案所在地(需要从empInfo中获取)
detail
.
setFileProvince
(
empInfo
.
getFileProvince
());
detail
.
setFileCity
(
empInfo
.
getFileCity
());
detail
.
setFileTown
(
empInfo
.
getFileTown
());
detailService
.
save
(
detail
);
}
successList
.
add
(
data
);
}
catch
(
Exception
e
)
{
log
.
error
(
"处理第"
+
data
.
getRowIndex
()
+
"行数据失败"
,
e
);
}
}
}
/**
* 保存任务表附件
*/
private
void
saveTaskAttachment
(
String
taskId
,
String
fileName
,
InputStream
inputStream
,
YifuUser
user
)
{
try
{
TAttaInfo
attaInfo
=
new
TAttaInfo
();
attaInfo
.
setAttaName
(
fileName
);
attaInfo
.
setRelationType
(
ArchiveConstants
.
ATTA_RELATION_TYPE_TASK
);
attaInfo
.
setDomainId
(
taskId
);
attaInfo
.
setStatus
(
ArchiveConstants
.
ATTA_STATUS_ENABLED
);
attaInfoService
.
save
(
attaInfo
);
}
catch
(
Exception
e
)
{
log
.
error
(
"保存任务表附件失败"
,
e
);
}
}
/**
* 建立任务和档案详情的关联关系
*/
private
void
createTaskArchiveRelations
(
String
taskId
,
List
<
ArchiveImportVO
>
successList
)
{
try
{
// 根据姓名、身份证、项目编码去重
Map
<
String
,
ArchiveImportVO
>
uniqueMap
=
new
HashMap
<>();
for
(
ArchiveImportVO
data
:
successList
)
{
String
uniqueKey
=
data
.
getEmpIdcard
()
+
"_"
+
data
.
getEmpName
()
+
"_"
+
data
.
getDeptNo
();
uniqueMap
.
put
(
uniqueKey
,
data
);
}
// 为每个唯一的人员创建关联关系
for
(
ArchiveImportVO
data
:
uniqueMap
.
values
())
{
// 查找对应的电子档案明细
LambdaQueryWrapper
<
TElectronicArchiveDetail
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
TElectronicArchiveDetail:
:
getEmpIdcard
,
data
.
getEmpIdcard
())
.
eq
(
TElectronicArchiveDetail:
:
getEmpName
,
data
.
getEmpName
())
.
eq
(
TElectronicArchiveDetail:
:
getDeptNo
,
data
.
getDeptNo
())
.
eq
(
TElectronicArchiveDetail:
:
getDeleteFlag
,
CommonConstants
.
ZERO_STRING
)
.
last
(
CommonConstants
.
LAST_ONE_SQL
);
TElectronicArchiveDetail
detail
=
detailService
.
getOne
(
wrapper
);
if
(
detail
!=
null
)
{
// 创建关联记录
TTaskArchiveRelation
relation
=
new
TTaskArchiveRelation
();
relation
.
setTaskId
(
taskId
);
relation
.
setArchiveDetailId
(
detail
.
getId
());
relationService
.
save
(
relation
);
}
}
log
.
info
(
"任务关联关系创建成功,任务ID:{},关联数量:{}"
,
taskId
,
uniqueMap
.
size
());
}
catch
(
Exception
e
)
{
log
.
error
(
"创建任务关联关系失败,任务ID:{}"
,
taskId
,
e
);
}
}
/**
* 第二步:导入ZIP文件
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
R
<?>
importZipFile
(
MultipartFile
file
,
String
taskId
)
{
YifuUser
user
=
SecurityUtils
.
getUser
();
if
(
null
==
user
)
{
return
R
.
failed
(
"用户未登录"
);
}
// 查询任务
TElectronicArchiveTask
task
=
taskService
.
getById
(
taskId
);
if
(
task
==
null
)
{
return
R
.
failed
(
"任务不存在"
);
}
if
(!
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
.
equals
(
task
.
getStatus
()))
{
return
R
.
failed
(
"任务状态不正确,无法上传ZIP文件"
);
}
File
tempZipFile
=
null
;
try
{
// 1. 校验ZIP大小
if
(
file
.
getSize
()
>
ArchiveConstants
.
ZIP_MAX_SIZE
)
{
return
R
.
failed
(
"ZIP文件大小不能超过500M"
);
}
// 2. 校验ZIP不为空
if
(
file
.
isEmpty
())
{
return
R
.
failed
(
"ZIP文件不能为空"
);
}
// 3. 校验同时上传任务数
long
runningTaskCount
=
taskService
.
count
(
new
LambdaQueryWrapper
<
TElectronicArchiveTask
>()
.
eq
(
TElectronicArchiveTask:
:
getStatus
,
ArchiveConstants
.
TASK_STATUS_GENERATING
));
if
(
runningTaskCount
>=
ArchiveConstants
.
MAX_CONCURRENT_TASKS
)
{
return
R
.
failed
(
"有其他客服正在上传中,请5分钟后重试"
);
}
// 更新任务信息
task
.
setUploadZipName
(
file
.
getOriginalFilename
());
task
.
setStatus
(
ArchiveConstants
.
TASK_STATUS_GENERATING
);
taskService
.
updateById
(
task
);
// 将ZIP文件保存到临时目录
String
tempDirPath
=
System
.
getProperty
(
"java.io.tmpdir"
)
+
File
.
separator
+
"zip_upload_"
+
taskId
;
File
tempDir
=
new
File
(
tempDirPath
);
if
(!
tempDir
.
exists
())
{
tempDir
.
mkdirs
();
}
tempZipFile
=
new
File
(
tempDir
,
file
.
getOriginalFilename
());
file
.
transferTo
(
tempZipFile
);
// 保存ZIP附件信息(记录临时文件路径)
TAttaInfo
zipAtta
=
new
TAttaInfo
();
zipAtta
.
setAttaName
(
file
.
getOriginalFilename
());
zipAtta
.
setAttaSize
(
file
.
getSize
());
zipAtta
.
setRelationType
(
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
);
zipAtta
.
setDomainId
(
taskId
);
zipAtta
.
setStatus
(
ArchiveConstants
.
ATTA_STATUS_DISABLED
);
zipAtta
.
setAttaSrc
(
tempZipFile
.
getAbsolutePath
());
// 临时存储文件路径
attaInfoService
.
save
(
zipAtta
);
// 调用异步处理
asyncProcessUpload
(
taskId
);
return
R
.
ok
(
"ZIP文件提交成功,正在处理中"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"导入ZIP文件失败"
,
e
);
// 清理临时文件
if
(
tempZipFile
!=
null
&&
tempZipFile
.
exists
())
{
FileUtil
.
del
(
tempZipFile
);
}
// 回滚任务状态
task
.
setStatus
(
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
taskService
.
updateById
(
task
);
return
R
.
failed
(
"导入ZIP文件失败:"
+
e
.
getMessage
());
}
}
/**
* 第三步:异步处理上传
*/
@Override
@Async
public
R
<?>
asyncProcessUpload
(
String
taskId
)
{
log
.
info
(
"开始异步处理任务:{}"
,
taskId
);
List
<
ArchiveFeedbackVO
>
feedbackList
=
new
ArrayList
<>();
File
tempDir
=
null
;
File
zipSourceFile
=
null
;
try
{
// 查询任务及关联的明细
TElectronicArchiveTask
task
=
taskService
.
getById
(
taskId
);
if
(
task
==
null
)
{
return
R
.
failed
(
"任务不存在"
);
}
// 查询ZIP附件(从附件导入中获取)
List
<
TAttaInfo
>
zipAttas
=
attaInfoService
.
list
(
new
LambdaQueryWrapper
<
TAttaInfo
>()
.
eq
(
TAttaInfo:
:
getDomainId
,
taskId
)
.
eq
(
TAttaInfo:
:
getRelationType
,
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
));
if
(
CollUtil
.
isEmpty
(
zipAttas
))
{
log
.
error
(
"ZIP附件不存在,任务ID:{}"
,
taskId
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"ZIP附件不存在"
);
}
TAttaInfo
zipAtta
=
zipAttas
.
get
(
0
);
// 从附件记录中获取ZIP文件路径
if
(
StrUtil
.
isBlank
(
zipAtta
.
getAttaSrc
()))
{
log
.
error
(
"ZIP文件路径为空,任务ID:{}"
,
taskId
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"ZIP文件路径为空"
);
}
zipSourceFile
=
new
File
(
zipAtta
.
getAttaSrc
());
if
(!
zipSourceFile
.
exists
())
{
log
.
error
(
"ZIP文件不存在:{},任务ID:{}"
,
zipAtta
.
getAttaSrc
(),
taskId
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"ZIP文件不存在"
);
}
// 获取任务关联的明细
List
<
TTaskArchiveRelation
>
relations
=
relationService
.
list
(
new
LambdaQueryWrapper
<
TTaskArchiveRelation
>()
.
eq
(
TTaskArchiveRelation:
:
getTaskId
,
taskId
));
if
(
CollUtil
.
isEmpty
(
relations
))
{
log
.
error
(
"任务没有关联的明细数据,任务ID:{}"
,
taskId
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"任务没有关联的明细数据"
);
}
List
<
String
>
detailIds
=
relations
.
stream
()
.
map
(
TTaskArchiveRelation:
:
getArchiveDetailId
)
.
collect
(
Collectors
.
toList
());
List
<
TElectronicArchiveDetail
>
details
=
detailService
.
listByIds
(
detailIds
);
Map
<
String
,
TElectronicArchiveDetail
>
detailMap
=
details
.
stream
()
.
collect
(
Collectors
.
toMap
(
d
->
d
.
getEmpIdcard
()
+
"_"
+
d
.
getEmpName
(),
d
->
d
));
// 创建临时目录用于解压ZIP文件
String
tempDirPath
=
System
.
getProperty
(
"java.io.tmpdir"
)
+
File
.
separator
+
"archive_"
+
taskId
+
"_"
+
System
.
currentTimeMillis
();
tempDir
=
new
File
(
tempDirPath
);
if
(!
tempDir
.
mkdirs
())
{
log
.
error
(
"创建临时目录失败:{}"
,
tempDirPath
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"创建临时目录失败"
);
}
// 解压ZIP文件
try
{
log
.
info
(
"开始解压ZIP文件:{},任务ID:{}"
,
zipSourceFile
.
getAbsolutePath
(),
taskId
);
cn
.
hutool
.
core
.
util
.
ZipUtil
.
unzip
(
zipSourceFile
,
tempDir
);
log
.
info
(
"ZIP文件解压成功,任务ID:{}"
,
taskId
);
}
catch
(
Exception
e
)
{
log
.
error
(
"解压ZIP文件失败,任务ID:{}"
,
taskId
,
e
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"解压ZIP文件失败:"
+
e
.
getMessage
());
}
// 获取ZIP包的根目录(第一级目录)
File
[]
zipRootDirs
=
tempDir
.
listFiles
(
File:
:
isDirectory
);
if
(
zipRootDirs
==
null
||
zipRootDirs
.
length
==
0
)
{
log
.
error
(
"ZIP文件中没有找到目录,任务ID:{}"
,
taskId
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"ZIP文件格式不正确"
);
}
File
zipRootDir
=
zipRootDirs
[
0
];
// 第一级目录
// 处理第二级目录(身份证+姓名目录)
File
[]
personDirs
=
zipRootDir
.
listFiles
(
File:
:
isDirectory
);
if
(
personDirs
==
null
||
personDirs
.
length
==
0
)
{
log
.
error
(
"ZIP文件中没有找到人员目录,任务ID:{}"
,
taskId
);
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
return
R
.
failed
(
"ZIP文件格式不正确"
);
}
// 遍历每个人员目录,递归处理所有附件
for
(
File
personDir
:
personDirs
)
{
processPersonDirectory
(
personDir
,
detailMap
,
feedbackList
,
taskId
);
}
// 处理完成,更新任务状态
task
.
setStatus
(
ArchiveConstants
.
TASK_STATUS_GENERATED
);
taskService
.
updateById
(
task
);
// 生成反馈表
generateFeedbackExcel
(
taskId
,
feedbackList
);
log
.
info
(
"任务处理完成,任务ID:{}"
,
taskId
);
return
R
.
ok
(
"处理完成"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"异步处理任务失败,任务ID:{}"
,
taskId
,
e
);
// 更新任务状态为失败
TElectronicArchiveTask
task
=
taskService
.
getById
(
taskId
);
if
(
task
!=
null
)
{
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
}
return
R
.
failed
(
"处理失败:"
+
e
.
getMessage
());
}
finally
{
// 清理临时解压目录
if
(
tempDir
!=
null
&&
tempDir
.
exists
())
{
try
{
FileUtil
.
del
(
tempDir
);
log
.
info
(
"清理临时解压目录成功:{}"
,
tempDir
.
getAbsolutePath
());
}
catch
(
Exception
e
)
{
log
.
error
(
"清理临时解压目录失败:{}"
,
tempDir
.
getAbsolutePath
(),
e
);
}
}
// 清理上传的ZIP文件
if
(
zipSourceFile
!=
null
&&
zipSourceFile
.
exists
())
{
try
{
FileUtil
.
del
(
zipSourceFile
.
getParentFile
());
log
.
info
(
"清理ZIP源文件成功:{}"
,
zipSourceFile
.
getAbsolutePath
());
}
catch
(
Exception
e
)
{
log
.
error
(
"清理ZIP源文件失败:{}"
,
zipSourceFile
.
getAbsolutePath
(),
e
);
}
}
}
}
/**
* 更新任务状态
*/
private
void
updateTaskStatus
(
TElectronicArchiveTask
task
,
String
status
)
{
task
.
setStatus
(
status
);
taskService
.
updateById
(
task
);
}
/**
* 生成任务编号
*/
@Override
public
synchronized
String
generateTaskCode
()
{
String
nowDay
=
DateUtil
.
getThisDay
();
Cache
cache
=
cacheManager
.
getCache
(
CacheConstants
.
ARCHIVE_TASK_CODE
);
int
nowNums
=
1
;
if
(
cache
!=
null
)
{
Object
nowNumObj
=
cache
.
get
(
nowDay
);
if
(
Common
.
isNotNull
(
nowNumObj
))
{
SimpleValueWrapper
value
=
(
SimpleValueWrapper
)
nowNumObj
;
nowNums
=
(
Integer
)
value
.
get
()
+
1
;
}
else
{
// 从数据库查询当天最大编号
LambdaQueryWrapper
<
TElectronicArchiveTask
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
likeRight
(
TElectronicArchiveTask:
:
getTaskCode
,
ArchiveConstants
.
TASK_CODE_PREFIX
+
nowDay
)
.
orderByDesc
(
TElectronicArchiveTask:
:
getTaskCode
)
.
last
(
"LIMIT 1"
);
TElectronicArchiveTask
lastTask
=
taskService
.
getOne
(
wrapper
);
if
(
lastTask
!=
null
&&
StrUtil
.
isNotBlank
(
lastTask
.
getTaskCode
()))
{
try
{
String
codeNum
=
lastTask
.
getTaskCode
().
substring
(
lastTask
.
getTaskCode
().
length
()
-
3
);
nowNums
=
Integer
.
parseInt
(
codeNum
)
+
1
;
}
catch
(
Exception
e
)
{
log
.
error
(
"解析任务编号失败"
,
e
);
nowNums
=
1
;
}
}
}
cache
.
put
(
nowDay
,
nowNums
);
}
return
ArchiveConstants
.
TASK_CODE_PREFIX
+
nowDay
+
String
.
format
(
"%03d"
,
nowNums
);
}
/**
* 处理单个人员目录
*/
private
void
processPersonDirectory
(
File
personDir
,
Map
<
String
,
TElectronicArchiveDetail
>
detailMap
,
List
<
ArchiveFeedbackVO
>
feedbackList
,
String
taskId
)
{
String
dirName
=
personDir
.
getName
();
log
.
info
(
"处理人员目录:{}"
,
dirName
);
// 解析身份证和姓名
Map
<
String
,
String
>
idNameMap
=
parseIdCardAndName
(
dirName
);
if
(
idNameMap
.
isEmpty
()
||
!
idNameMap
.
containsKey
(
"idCard"
)
||
!
idNameMap
.
containsKey
(
"name"
))
{
// 目录格式不正确
ArchiveFeedbackVO
feedback
=
new
ArchiveFeedbackVO
();
feedback
.
setEmpName
(
dirName
);
feedback
.
setEmpIdcard
(
""
);
feedback
.
setProcessResult
(
ArchiveConstants
.
PROCESS_RESULT_SKIP
);
feedback
.
setFailReason
(
"目录名称格式不正确,无法解析身份证和姓名"
);
feedbackList
.
add
(
feedback
);
return
;
}
String
idCard
=
idNameMap
.
get
(
"idCard"
);
String
name
=
idNameMap
.
get
(
"name"
);
String
uniqueKey
=
idCard
+
"_"
+
name
;
// 检查是否在第一步导入的数据中
TElectronicArchiveDetail
detail
=
detailMap
.
get
(
uniqueKey
);
if
(
detail
==
null
)
{
// 不在第一步的文档中
ArchiveFeedbackVO
feedback
=
new
ArchiveFeedbackVO
();
feedback
.
setEmpName
(
name
);
feedback
.
setEmpIdcard
(
idCard
);
feedback
.
setDeptNo
(
""
);
feedback
.
setDeptName
(
""
);
feedback
.
setProcessResult
(
ArchiveConstants
.
PROCESS_RESULT_SKIP
);
feedback
.
setFailReason
(
"压缩包中未找到对应文件夹,跳过处理"
);
feedbackList
.
add
(
feedback
);
return
;
}
// 处理第三级目录(资料类型或直接是文件)
File
[]
subFiles
=
personDir
.
listFiles
();
if
(
subFiles
==
null
||
subFiles
.
length
==
0
)
{
// 文件夹为空
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
""
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"文件夹为空"
);
feedbackList
.
add
(
feedback
);
return
;
}
// 用于记录该人员的所有资料类型
Set
<
String
>
materialTypes
=
new
HashSet
<>();
// 遍历第三级,递归处理所有文件
for
(
File
subFile
:
subFiles
)
{
if
(
subFile
.
isDirectory
())
{
// 是资料类型目录
String
materialType
=
subFile
.
getName
();
if
(!
isValidMaterialType
(
materialType
))
{
// 不是有效的资料类型,跳过
continue
;
}
// 递归处理资料类型目录下的所有文件(包括子目录)
processDirectoryRecursively
(
subFile
,
detail
,
materialType
,
feedbackList
,
materialTypes
);
}
else
{
// 直接是文件,默认为存量类型
processFile
(
subFile
,
detail
,
ArchiveConstants
.
MATERIAL_TYPE_STOCK
,
feedbackList
,
materialTypes
);
}
}
// 更新明细表的资料类型和状态
if
(!
materialTypes
.
isEmpty
())
{
updateDetailMaterialType
(
detail
,
materialTypes
);
}
}
/**
* 递归处理目录下的所有文件(包括子目录)
*/
private
void
processDirectoryRecursively
(
File
directory
,
TElectronicArchiveDetail
detail
,
String
materialType
,
List
<
ArchiveFeedbackVO
>
feedbackList
,
Set
<
String
>
materialTypes
)
{
File
[]
files
=
directory
.
listFiles
();
if
(
files
==
null
||
files
.
length
==
0
)
{
// 文件夹为空
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"文件夹为空"
);
feedbackList
.
add
(
feedback
);
return
;
}
// 递归处理该目录下的所有文件和子目录
for
(
File
file
:
files
)
{
if
(
file
.
isDirectory
())
{
// 如果是子目录,递归处理
processDirectoryRecursively
(
file
,
detail
,
materialType
,
feedbackList
,
materialTypes
);
}
else
if
(
file
.
isFile
())
{
// 如果是文件,上传到阿里云并生成TAttaInfo记录
processFile
(
file
,
detail
,
materialType
,
feedbackList
,
materialTypes
);
}
}
}
/**
* 处理单个文件(上传到阿里云OSS,每个文件生成一条TAttaInfo记录)
*/
private
void
processFile
(
File
file
,
TElectronicArchiveDetail
detail
,
String
materialType
,
List
<
ArchiveFeedbackVO
>
feedbackList
,
Set
<
String
>
materialTypes
)
{
String
fileName
=
file
.
getName
();
long
fileSize
=
file
.
length
();
log
.
info
(
"处理文件:{},大小:{},电子档案详情ID:{}"
,
fileName
,
fileSize
,
detail
.
getId
());
// 1. 校验文件大小
if
(
fileSize
>
ArchiveConstants
.
SINGLE_FILE_MAX_SIZE
)
{
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"单个文件大小超过15M:"
+
fileName
);
feedbackList
.
add
(
feedback
);
return
;
}
// 2. 校验文件格式
if
(!
checkFileFormat
(
fileName
))
{
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"文件格式不符,文件格式需为png\\jpg\\jpeg\\xlsx\\xls\\doc\\docx\\pdf\\ppt\\pptx\\txt:"
+
fileName
);
feedbackList
.
add
(
feedback
);
return
;
}
// 3. 上传文件到阿里云OSS
try
{
// 构建OSS目录路径
String
ossDirectory
=
buildOssDirectory
(
detail
,
materialType
);
// 转换为MultipartFile
MultipartFile
multipartFile
=
fileToMultipartFile
(
file
);
if
(
multipartFile
==
null
)
{
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"文件转换失败:"
+
fileName
);
feedbackList
.
add
(
feedback
);
return
;
}
// 上传文件,uploadFileReturnAtta会自动生成TAttaInfo记录
// domainId为电子档案详情表的id(detail.getId())
R
<
TAttaInfo
>
uploadResult
=
fileUploadService
.
uploadFileReturnAtta
(
multipartFile
,
ossDirectory
,
getMaterialTypeCode
(
materialType
),
detail
.
getId
()
);
if
(
uploadResult
==
null
||
!
R
.
isSuccess
(
uploadResult
))
{
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"文件上传失败:"
+
fileName
+
",原因:"
+
(
uploadResult
!=
null
?
uploadResult
.
getMsg
()
:
"未知错误"
));
feedbackList
.
add
(
feedback
);
return
;
}
// 上传成功,记录附件信息
TAttaInfo
attaInfo
=
uploadResult
.
getData
();
log
.
info
(
"文件上传成功:{},附件ID:{},domainId:{}"
,
fileName
,
attaInfo
.
getId
(),
attaInfo
.
getDomainId
());
// 记录该人员的资料类型
materialTypes
.
add
(
materialType
);
// 生成成功反馈
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_SUCCESS
,
""
);
feedbackList
.
add
(
feedback
);
}
catch
(
Exception
e
)
{
log
.
error
(
"上传文件失败:{},电子档案详情ID:{}"
,
fileName
,
detail
.
getId
(),
e
);
ArchiveFeedbackVO
feedback
=
createFeedbackVO
(
detail
,
materialType
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
,
"文件上传异常:"
+
fileName
+
",原因:"
+
e
.
getMessage
());
feedbackList
.
add
(
feedback
);
}
}
/**
* 构建OSS目录路径
*/
private
String
buildOssDirectory
(
TElectronicArchiveDetail
detail
,
String
materialType
)
{
// 目录格式:项目编码-姓名-身份证号/资料类型
return
detail
.
getDeptNo
()
+
"-"
+
detail
.
getEmpName
()
+
"-"
+
detail
.
getEmpIdcard
()
+
"/"
+
materialType
;
}
/**
* 创建反馈VO
*/
private
ArchiveFeedbackVO
createFeedbackVO
(
TElectronicArchiveDetail
detail
,
String
materialType
,
String
processResult
,
String
failReason
)
{
ArchiveFeedbackVO
feedback
=
new
ArchiveFeedbackVO
();
feedback
.
setEmpName
(
detail
.
getEmpName
());
feedback
.
setEmpIdcard
(
detail
.
getEmpIdcard
());
feedback
.
setDeptNo
(
detail
.
getDeptNo
());
feedback
.
setDeptName
(
detail
.
getDeptName
());
feedback
.
setMaterialType
(
materialType
);
feedback
.
setProcessResult
(
processResult
);
feedback
.
setFailReason
(
failReason
);
return
feedback
;
}
/**
* 判断是否是有效的资料类型
*/
private
boolean
isValidMaterialType
(
String
typeName
)
{
return
ArchiveConstants
.
MATERIAL_TYPE_STOCK
.
equals
(
typeName
)
||
ArchiveConstants
.
MATERIAL_TYPE_NEW
.
equals
(
typeName
)
||
ArchiveConstants
.
MATERIAL_TYPE_RENEW
.
equals
(
typeName
)
||
ArchiveConstants
.
MATERIAL_TYPE_LEAVE
.
equals
(
typeName
);
}
/**
* 更新明细表的资料类型和状态
*/
private
void
updateDetailMaterialType
(
TElectronicArchiveDetail
detail
,
Set
<
String
>
newMaterialTypes
)
{
// 查找是否存在相同身份证姓名和项目编码的可用明细
LambdaQueryWrapper
<
TElectronicArchiveDetail
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
TElectronicArchiveDetail:
:
getEmpIdcard
,
detail
.
getEmpIdcard
())
.
eq
(
TElectronicArchiveDetail:
:
getEmpName
,
detail
.
getEmpName
())
.
eq
(
TElectronicArchiveDetail:
:
getDeptNo
,
detail
.
getDeptNo
())
.
eq
(
TElectronicArchiveDetail:
:
getStatus
,
ArchiveConstants
.
DETAIL_STATUS_ENABLED
)
.
eq
(
TElectronicArchiveDetail:
:
getDeleteFlag
,
CommonConstants
.
ZERO_STRING
)
.
last
(
CommonConstants
.
LAST_ONE_SQL
);
TElectronicArchiveDetail
existDetail
=
detailService
.
getOne
(
wrapper
);
if
(
existDetail
!=
null
)
{
// 存在可用明细,合并资料类型
Set
<
String
>
existTypes
=
new
HashSet
<>();
if
(
StrUtil
.
isNotBlank
(
existDetail
.
getMaterialType
()))
{
existTypes
.
addAll
(
Arrays
.
asList
(
existDetail
.
getMaterialType
().
split
(
","
)));
}
existTypes
.
addAll
(
newMaterialTypes
);
// 更新资料类型
existDetail
.
setMaterialType
(
String
.
join
(
","
,
existTypes
));
detailService
.
updateById
(
existDetail
);
}
else
{
// 不存在可用明细,更新当前明细为可用
detail
.
setMaterialType
(
String
.
join
(
","
,
newMaterialTypes
));
detail
.
setStatus
(
ArchiveConstants
.
DETAIL_STATUS_ENABLED
);
detailService
.
updateById
(
detail
);
}
}
/**
* File转MultipartFile
*/
private
MultipartFile
fileToMultipartFile
(
File
file
)
{
try
{
FileInputStream
input
=
new
FileInputStream
(
file
);
return
new
MockMultipartFile
(
"file"
,
file
.
getName
(),
null
,
input
);
}
catch
(
Exception
e
)
{
log
.
error
(
"File转MultipartFile失败"
,
e
);
return
null
;
}
}
/**
* 生成反馈表Excel
*/
private
void
generateFeedbackExcel
(
String
taskId
,
List
<
ArchiveFeedbackVO
>
feedbackList
)
{
if
(
CollUtil
.
isEmpty
(
feedbackList
))
{
log
.
info
(
"没有反馈数据,跳过生成反馈表"
);
return
;
}
try
{
// 创建临时文件
String
tempFilePath
=
System
.
getProperty
(
"java.io.tmpdir"
)
+
File
.
separator
+
"feedback_"
+
taskId
+
"_"
+
System
.
currentTimeMillis
()
+
".xlsx"
;
File
feedbackFile
=
new
File
(
tempFilePath
);
// 使用EasyExcel生成反馈表
EasyExcel
.
write
(
feedbackFile
,
ArchiveFeedbackVO
.
class
)
.
sheet
(
"处理结果反馈"
)
.
doWrite
(
feedbackList
);
// 上传反馈表到OSS
YifuUser
user
=
SecurityUtils
.
getUser
();
if
(
user
!=
null
)
{
R
<
TAttaInfo
>
uploadResult
=
fileUploadService
.
uploadFileReturnAtta
(
fileToMultipartFile
(
feedbackFile
),
"archive/feedback"
,
ArchiveConstants
.
ATTA_RELATION_TYPE_FEEDBACK
,
taskId
);
if
(
uploadResult
!=
null
&&
R
.
isSuccess
(
uploadResult
))
{
log
.
info
(
"反馈表生成成功,任务ID:{}"
,
taskId
);
}
else
{
log
.
error
(
"反馈表上传失败,任务ID:{}"
,
taskId
);
}
}
// 删除临时文件
FileUtil
.
del
(
feedbackFile
);
}
catch
(
Exception
e
)
{
log
.
error
(
"生成反馈表失败,任务ID:{}"
,
taskId
,
e
);
}
}
/**
* 解析身份证和姓名信息
* 支持格式:姓名-身份证号、身份证号-姓名、姓名身份证号、身份证号姓名
*/
private
Map
<
String
,
String
>
parseIdCardAndName
(
String
folderName
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<>();
// 尝试用-分隔
if
(
folderName
.
contains
(
"-"
))
{
String
[]
parts
=
folderName
.
split
(
"-"
);
if
(
parts
.
length
==
2
)
{
// 判断哪个是身份证号(18位数字)
if
(
parts
[
0
].
matches
(
"\\d{18}"
))
{
result
.
put
(
"idCard"
,
parts
[
0
]);
result
.
put
(
"name"
,
parts
[
1
]);
}
else
if
(
parts
[
1
].
matches
(
"\\d{18}"
))
{
result
.
put
(
"name"
,
parts
[
0
]);
result
.
put
(
"idCard"
,
parts
[
1
]);
}
}
}
else
{
// 尝试提取18位身份证号
int
idCardStart
=
-
1
;
for
(
int
i
=
0
;
i
<=
folderName
.
length
()
-
18
;
i
++)
{
String
sub
=
folderName
.
substring
(
i
,
i
+
18
);
if
(
sub
.
matches
(
"\\d{18}"
))
{
idCardStart
=
i
;
break
;
}
}
if
(
idCardStart
>=
0
)
{
String
idCard
=
folderName
.
substring
(
idCardStart
,
idCardStart
+
18
);
String
name
=
folderName
.
substring
(
0
,
idCardStart
)
+
folderName
.
substring
(
idCardStart
+
18
);
result
.
put
(
"idCard"
,
idCard
);
result
.
put
(
"name"
,
name
);
}
}
return
result
;
}
/**
* 校验文件格式
*/
private
boolean
checkFileFormat
(
String
fileName
)
{
if
(
StrUtil
.
isBlank
(
fileName
))
{
return
false
;
}
String
ext
=
FileUtil
.
extName
(
fileName
).
toLowerCase
();
for
(
String
format
:
ArchiveConstants
.
SUPPORTED_FILE_FORMATS
)
{
if
(
format
.
equalsIgnoreCase
(
ext
))
{
return
true
;
}
}
return
false
;
}
/**
* 资料类型名称转换为编码
*/
private
String
getMaterialTypeCode
(
String
typeName
)
{
if
(
ArchiveConstants
.
MATERIAL_TYPE_STOCK
.
equals
(
typeName
))
{
return
ArchiveConstants
.
MATERIAL_TYPE_CODE_STOCK
;
}
else
if
(
ArchiveConstants
.
MATERIAL_TYPE_NEW
.
equals
(
typeName
))
{
return
ArchiveConstants
.
MATERIAL_TYPE_CODE_NEW
;
}
else
if
(
ArchiveConstants
.
MATERIAL_TYPE_RENEW
.
equals
(
typeName
))
{
return
ArchiveConstants
.
MATERIAL_TYPE_CODE_RENEW
;
}
else
if
(
ArchiveConstants
.
MATERIAL_TYPE_LEAVE
.
equals
(
typeName
))
{
return
ArchiveConstants
.
MATERIAL_TYPE_CODE_LEAVE
;
}
return
ArchiveConstants
.
MATERIAL_TYPE_CODE_STOCK
;
// 默认存量
}
/**
* 单个新增人员附件
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
R
<?>
uploadSinglePersonArchive
(
String
empIdcard
,
String
empName
,
String
deptNo
,
String
deptName
,
String
materialType
,
MultipartFile
[]
files
)
{
YifuUser
user
=
SecurityUtils
.
getUser
();
if
(
null
==
user
)
{
return
R
.
failed
(
"用户未登录"
);
}
// 参数校验
if
(
StrUtil
.
isBlank
(
empIdcard
)
||
StrUtil
.
isBlank
(
empName
)
||
StrUtil
.
isBlank
(
deptNo
)
||
StrUtil
.
isBlank
(
deptName
)
||
StrUtil
.
isBlank
(
materialType
))
{
return
R
.
failed
(
"参数不能为空"
);
}
// 校验附件
if
(
files
==
null
||
files
.
length
==
0
)
{
return
R
.
failed
(
"附件不能为空"
);
}
// 校验资料类型是否有效
if
(!
isValidMaterialType
(
materialType
))
{
return
R
.
failed
(
"资料类型不正确,必须为:存量、新签、续签、离职"
);
}
// 校验身份证格式
if
(!
empIdcard
.
matches
(
"\\d{18}"
))
{
return
R
.
failed
(
"身份证号格式不正确"
);
}
try
{
// 1. 查询项目信息获取客户信息
TSettleDomainSelectVo
settleResult
=
archivesDaprUtil
.
selectDeptByNo
(
deptNo
);
if
(
settleResult
==
null
)
{
return
R
.
failed
(
"项目编码["
+
deptNo
+
"]信息不存在"
);
}
// 2. 查询人员档案信息获取档案所在地
IdNameNoVo
vo
=
new
IdNameNoVo
();
vo
.
setName
(
empName
);
vo
.
setNo
(
empIdcard
);
R
<
TEmployeeInfo
>
empResult
=
archivesDaprUtil
.
getTEmployeeInfoByIdcardAndName
(
vo
);
if
(
empResult
==
null
||
empResult
.
getData
()
==
null
)
{
return
R
.
failed
(
"人员档案信息不存在"
);
}
TEmployeeInfo
empInfo
=
empResult
.
getData
();
// 3. 查找是否存在相同的电子档案明细
LambdaQueryWrapper
<
TElectronicArchiveDetail
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
TElectronicArchiveDetail:
:
getEmpIdcard
,
empIdcard
)
.
eq
(
TElectronicArchiveDetail:
:
getEmpName
,
empName
)
.
eq
(
TElectronicArchiveDetail:
:
getDeptNo
,
deptNo
)
.
eq
(
TElectronicArchiveDetail:
:
getStatus
,
ArchiveConstants
.
DETAIL_STATUS_ENABLED
)
.
eq
(
TElectronicArchiveDetail:
:
getDeleteFlag
,
CommonConstants
.
ZERO_STRING
)
.
last
(
CommonConstants
.
LAST_ONE_SQL
);
TElectronicArchiveDetail
detail
=
detailService
.
getOne
(
wrapper
);
// 4. 如果不存在,创建新的明细
if
(
detail
==
null
)
{
detail
=
new
TElectronicArchiveDetail
();
detail
.
setEmpName
(
empName
);
detail
.
setEmpIdcard
(
empIdcard
);
detail
.
setDeptNo
(
deptNo
);
detail
.
setDeptName
(
deptName
);
detail
.
setCustomerName
(
settleResult
.
getCustomerName
());
detail
.
setCustomerCode
(
settleResult
.
getCustomerCode
());
detail
.
setMaterialType
(
materialType
);
detail
.
setStatus
(
ArchiveConstants
.
DETAIL_STATUS_ENABLED
);
detail
.
setDeleteFlag
(
CommonConstants
.
ZERO_STRING
);
detail
.
setFileProvince
(
empInfo
.
getFileProvince
());
detail
.
setFileCity
(
empInfo
.
getFileCity
());
detail
.
setFileTown
(
empInfo
.
getFileTown
());
detailService
.
save
(
detail
);
}
else
{
// 存在则更新资料类型(追加)
Set
<
String
>
existTypes
=
new
HashSet
<>();
if
(
StrUtil
.
isNotBlank
(
detail
.
getMaterialType
()))
{
existTypes
.
addAll
(
Arrays
.
asList
(
detail
.
getMaterialType
().
split
(
","
)));
}
existTypes
.
add
(
materialType
);
detail
.
setMaterialType
(
String
.
join
(
","
,
existTypes
));
detailService
.
updateById
(
detail
);
}
// 5. 上传附件到阿里云OSS
int
successCount
=
0
;
int
failCount
=
0
;
StringBuilder
failReasons
=
new
StringBuilder
();
for
(
MultipartFile
file
:
files
)
{
if
(
file
==
null
||
file
.
isEmpty
())
{
continue
;
}
// 校验文件大小
if
(
file
.
getSize
()
>
ArchiveConstants
.
SINGLE_FILE_MAX_SIZE
)
{
failCount
++;
failReasons
.
append
(
file
.
getOriginalFilename
()).
append
(
":文件大小超过15M;"
);
continue
;
}
// 校验文件格式
String
fileName
=
file
.
getOriginalFilename
();
if
(!
checkFileFormat
(
fileName
))
{
failCount
++;
failReasons
.
append
(
fileName
).
append
(
":文件格式不符;"
);
continue
;
}
try
{
// 构建OSS目录路径
String
ossDirectory
=
buildOssDirectory
(
detail
,
materialType
);
// 上传文件到OSS
R
<
TAttaInfo
>
uploadResult
=
fileUploadService
.
uploadFileReturnAtta
(
file
,
ossDirectory
,
getMaterialTypeCode
(
materialType
),
detail
.
getId
()
);
if
(
uploadResult
!=
null
&&
R
.
isSuccess
(
uploadResult
))
{
successCount
++;
}
else
{
failCount
++;
failReasons
.
append
(
fileName
).
append
(
":上传失败;"
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"上传文件失败:{}"
,
fileName
,
e
);
failCount
++;
failReasons
.
append
(
fileName
).
append
(
":上传异常;"
);
}
}
// 6. 返回处理结果
String
resultMsg
=
String
.
format
(
"处理完成,成功:%d个,失败:%d个"
,
successCount
,
failCount
);
if
(
failCount
>
0
)
{
resultMsg
+=
"。失败原因:"
+
failReasons
.
toString
();
}
return
R
.
ok
(
null
,
resultMsg
);
}
catch
(
Exception
e
)
{
log
.
error
(
"单个新增人员附件失败"
,
e
);
return
R
.
failed
(
"处理失败:"
+
e
.
getMessage
());
}
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/FileUploadServiceImpl.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
.
impl
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.batch.mapper.SysConfigLimitMapper
;
import
com.yifu.cloud.plus.v1.batch.service.FileUploadService
;
import
com.yifu.cloud.plus.v1.batch.service.TAttaInfoService
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.ResultConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.OSSUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.FileVo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.AuthorityUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.time.LocalDateTime
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.Set
;
import
java.util.concurrent.atomic.AtomicInteger
;
@Service
@RequiredArgsConstructor
@Slf4j
public
class
FileUploadServiceImpl
implements
FileUploadService
{
private
final
OSSUtil
ossUtil
;
private
final
TAttaInfoService
tAttaInfoService
;
private
AtomicInteger
atomicInteger
=
new
AtomicInteger
(
0
);
//初始化附件上传队列上限值
private
int
maxLimit
=
1
;
private
final
SysConfigLimitMapper
configLimitMapper
;
@Override
public
R
<
TAttaInfo
>
uploadFileReturnAtta
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domainId
)
throws
IOException
{
if
(
null
==
file
)
{
return
R
.
failed
(
"文件删除异常,请重新上传!"
);
}
String
fileName
=
file
.
getOriginalFilename
();
if
(
fileName
==
null
||
Common
.
isEmpty
(
fileName
))
{
return
R
.
failed
(
"文件名不能为空!!"
);
}
if
(
fileName
.
length
()
>
100
)
{
return
R
.
failed
(
"文件名不能超过100个字符!"
);
}
//filePath不传默认存储空间的根目录
//jpg,jpeg,png,bmp
String
key
=
""
;
if
(
Common
.
isNotNull
(
filePath
))
{
key
=
filePath
+
"/"
+
System
.
currentTimeMillis
()
+
fileName
;
}
else
{
key
=
System
.
currentTimeMillis
()
+
fileName
;
}
if
(!
Common
.
checkFile
(
key
))
{
return
R
.
failed
(
"非法上传类型:"
+
fileName
);
}
boolean
flag
=
ossUtil
.
uploadFileByStream
(
file
.
getInputStream
(),
key
,
null
);
TAttaInfo
attaInfo
;
URL
url
;
if
(
flag
)
{
log
.
info
(
"文件:"
+
fileName
+
"上传到存储空间"
+
ossUtil
.
getBucketName
()
+
"成功!"
);
attaInfo
=
initUnitAttaForInsert
(
fileName
,
key
,
file
.
getSize
());
attaInfo
.
setRelationType
(
type
);
try
{
attaInfo
.
setDomainId
(
domainId
);
Set
<
String
>
dbAuthsSet
=
new
HashSet
<>();
Collection
<?
extends
GrantedAuthority
>
authorities
=
AuthorityUtils
.
createAuthorityList
(
dbAuthsSet
.
toArray
(
new
String
[
0
]));
YifuUser
user
=
new
YifuUser
(
"8"
,
1L
,
""
,
"电子档案上传"
,
"电子档案上传"
,
"0"
,
SecurityConstants
.
BCRYPT
+
"123456"
,
"12345678911"
,
true
,
true
,
true
,
true
,
"1"
,
authorities
,
"1"
,
null
,
null
,
null
,
null
);
attaInfo
.
setCreateBy
(
user
.
getId
());
attaInfo
.
setCreateName
(
user
.
getNickname
());
attaInfo
=
tAttaInfoService
.
add
(
attaInfo
);
}
catch
(
Exception
e
)
{
log
.
error
(
"OSS文件上传异常:"
+
e
.
getMessage
());
ossUtil
.
deleteObject
(
null
,
key
);
return
R
.
failed
(
"上传异常:"
+
e
.
getMessage
());
}
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
attaInfo
.
setAttaUrl
(
String
.
valueOf
(
url
));
return
R
.
ok
(
attaInfo
);
}
else
{
return
R
.
failed
(
"fail:上传异常"
);
}
}
@Override
public
R
<
FileVo
>
uploadImg
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domain
)
throws
IOException
{
if
(
null
==
file
)
{
return
R
.
failed
(
"文件删除异常,请重新上传!"
);
}
String
fileName
=
file
.
getOriginalFilename
();
if
(
Common
.
isEmpty
(
fileName
))
{
return
R
.
failed
(
"文件名不能为空!"
);
}
if
(
fileName
.
length
()
>
100
)
{
return
R
.
failed
(
"文件名不能超过100个字符!"
);
}
//filePath不传默认存储空间的根目录
//jpg,jpeg,png,bmp
String
key
=
""
;
if
(
Common
.
isNotNull
(
filePath
))
{
key
=
filePath
+
"/"
+
System
.
currentTimeMillis
()
+
fileName
;
}
else
{
key
=
System
.
currentTimeMillis
()
+
fileName
;
}
if
(!
Common
.
checkFile
(
key
))
{
return
R
.
failed
(
"非法上传类型!"
);
}
boolean
flag
=
ossUtil
.
uploadFileByStream
(
file
.
getInputStream
(),
key
,
null
);
FileVo
fileVo
;
TAttaInfo
attaInfo
;
URL
url
;
if
(
flag
)
{
log
.
info
(
"文件:"
+
fileName
+
"上传至存储空间"
+
ossUtil
.
getBucketName
()
+
"成功!"
);
attaInfo
=
initUnitAttaForInsert
(
fileName
,
key
,
file
.
getSize
());
attaInfo
.
setRelationType
(
type
);
try
{
attaInfo
.
setDomainId
(
domain
);
attaInfo
=
tAttaInfoService
.
add
(
attaInfo
);
}
catch
(
Exception
e
)
{
log
.
error
(
"OSS文件上传接口异常:"
+
e
.
getMessage
());
ossUtil
.
deleteObject
(
null
,
key
);
return
R
.
failed
(
"fail:"
+
e
.
getMessage
());
}
//有实体id则插入关系,用于编辑
if
(
Common
.
isNotNull
(
domain
))
{
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
fileVo
=
new
FileVo
(
attaInfo
.
getId
(),
attaInfo
.
getAttaName
(),
url
.
toString
());
return
R
.
ok
(
fileVo
,
"success"
);
}
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
fileVo
=
new
FileVo
(
attaInfo
.
getId
(),
attaInfo
.
getAttaName
(),
url
.
toString
());
return
R
.
ok
(
fileVo
,
"success"
);
}
else
{
return
R
.
failed
(
"fail:上传失败"
);
}
}
/**
* 对象初始化
* @param fileName
* @param key
* @param fileSize
* @return
*/
private
TAttaInfo
initUnitAttaForInsert
(
String
fileName
,
String
key
,
long
fileSize
)
{
TAttaInfo
unitAtta
=
new
TAttaInfo
();
char
slash
=
'/'
;
char
point
=
'.'
;
if
(
fileName
.
lastIndexOf
(
slash
)
>=
0
)
{
unitAtta
.
setAttaName
(
fileName
.
substring
(
fileName
.
lastIndexOf
(
slash
)));
}
else
{
unitAtta
.
setAttaName
(
fileName
);
}
unitAtta
.
setAttaSize
(
fileSize
);
unitAtta
.
setAttaSrc
(
key
);
if
(
key
.
lastIndexOf
(
point
)
>=
0
)
{
unitAtta
.
setAttaType
(
key
.
substring
(
key
.
lastIndexOf
(
point
)));
}
unitAtta
.
setCreateTime
(
LocalDateTime
.
now
());
return
unitAtta
;
}
/**
* @Author fxj
* @Description 整合接口
* @Date 15:24 2024/9/24
* @Param
* @return
**/
@Override
public
R
uploadAsso
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domain
,
String
uploadType
){
return
getR
(
file
,
filePath
,
type
,
domain
,
uploadType
);
}
public
R
getR
(
MultipartFile
file
,
String
filePath
,
String
type
,
String
domain
,
String
uploadType
)
{
maxLimit
=
configLimitMapper
.
getSysConfigLimitByKey
(
"UPLOAD_MAX_LIMIT"
);
if
(
atomicInteger
.
incrementAndGet
()
<=
maxLimit
){
try
{
if
(
CommonConstants
.
ZERO_STRING
.
equals
(
uploadType
)){
return
uploadImg
(
file
,
filePath
,
type
,
domain
);
}
else
if
(
CommonConstants
.
ONE_STRING
.
equals
(
uploadType
)){
return
uploadFileReturnAtta
(
file
,
filePath
,
type
,
domain
);
}
}
catch
(
Exception
e
){
log
.
error
(
"附件上传异常:"
,
e
);
}
finally
{
atomicInteger
.
decrementAndGet
();
}
}
else
{
atomicInteger
.
decrementAndGet
();
log
.
error
(
"超出阈值:"
+
ResultConstants
.
FILE_UPLOADING_DATA
);
return
R
.
failed
(
ResultConstants
.
FILE_UPLOADING_DATA
);
}
return
null
;
}
@Override
public
boolean
checkFileExists
(
String
filePath
)
{
try
{
return
ossUtil
.
doesObjectExist
(
null
,
filePath
);
}
catch
(
Exception
e
)
{
log
.
error
(
"检查文件是否存在失败:{}"
,
filePath
,
e
);
return
false
;
}
}
}
\ No newline at end of file
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/TAttaInfoServiceImpl.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
.
impl
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.batch.mapper.TAttaInfoMapper
;
import
com.yifu.cloud.plus.v1.batch.service.TAttaInfoService
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.OSSUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.net.URL
;
import
java.util.List
;
/**
* 附件信息表
*
* @author pwang
* @date 2021-02-19 16:16:07
*/
@Service
public
class
TAttaInfoServiceImpl
extends
ServiceImpl
<
TAttaInfoMapper
,
TAttaInfo
>
implements
TAttaInfoService
{
@Autowired
private
OSSUtil
ossUtil
;
@Override
public
List
<
TAttaInfo
>
getTAttaInfoListByDoMainId
(
String
domainId
)
{
return
baseMapper
.
getTAttaInfoListByDoMainId
(
domainId
);
}
@Override
public
TAttaInfo
add
(
TAttaInfo
attaInfo
)
{
this
.
save
(
attaInfo
);
return
attaInfo
;
}
@Override
public
Boolean
updateDomainId
(
String
domainId
,
List
<
String
>
ids
){
if
(
Common
.
isEmpty
(
domainId
)
||
!
Common
.
isNotEmpty
(
ids
)){
return
false
;
}
return
baseMapper
.
updateDomainId
(
domainId
,
ids
)
>
0
;
}
@Override
public
R
<
List
<
TAttaInfo
>>
getAttaByApplyId
(
String
applyId
)
{
List
<
TAttaInfo
>
list
=
baseMapper
.
getAttaByApplyId
(
applyId
);
if
(
Common
.
isNotNull
(
list
))
{
URL
url
;
for
(
TAttaInfo
atta:
list
)
{
url
=
ossUtil
.
getObjectUrl
(
null
,
atta
.
getAttaSrc
());
atta
.
setAttaUrl
(
url
.
toString
());
}
return
R
.
ok
(
list
);
}
else
{
return
R
.
failed
(
"没有附件"
);
}
}
@Override
public
void
deleteByDomainId
(
String
domainId
)
{
baseMapper
.
deleteByDomainId
(
domainId
);
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/TElectronicArchiveDetailServiceImpl.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
.
impl
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.alibaba.excel.EasyExcel
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yifu.cloud.plus.v1.batch.constants.ArchiveConstants
;
import
com.yifu.cloud.plus.v1.batch.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
import
com.yifu.cloud.plus.v1.batch.mapper.TElectronicArchiveDetailMapper
;
import
com.yifu.cloud.plus.v1.batch.service.TAttaInfoService
;
import
com.yifu.cloud.plus.v1.batch.service.TElectronicArchiveDetailService
;
import
com.yifu.cloud.plus.v1.batch.service.TElectronicArchiveTaskService
;
import
com.yifu.cloud.plus.v1.batch.service.TTaskArchiveRelationService
;
import
com.yifu.cloud.plus.v1.batch.vo.*
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.OSSUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.bean.OSSObjectBean
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.log4j.Log4j2
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.net.URLEncoder
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.*
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipOutputStream
;
/**
* 电子档案明细表
*
* @author huych
* @date 2025-12-17 11:03:37
*/
@Log4j2
@Service
@RequiredArgsConstructor
public
class
TElectronicArchiveDetailServiceImpl
extends
ServiceImpl
<
TElectronicArchiveDetailMapper
,
TElectronicArchiveDetail
>
implements
TElectronicArchiveDetailService
{
private
final
TAttaInfoService
attaInfoService
;
private
final
TTaskArchiveRelationService
relationService
;
private
final
TElectronicArchiveTaskService
taskService
;
@Autowired
private
OSSUtil
ossUtil
;
/**
* 电子档案明细表简单分页查询
* @param tElectronicArchiveDetail 电子档案明细表
* @return
*/
@Override
public
IPage
<
TElectronicArchiveDetail
>
getTElectronicArchiveDetailPage
(
Page
<
TElectronicArchiveDetail
>
page
,
TElectronicArchiveDetailSearchVo
tElectronicArchiveDetail
){
return
baseMapper
.
getTElectronicArchiveDetailPage
(
page
,
tElectronicArchiveDetail
);
}
/**
* 通过id查询电子档案明细表详情
* 附件信息按任务分组展示,每个任务的附件按资料类型分类
*
* @param id 明细ID
* @return 明细详情
*/
@Override
public
R
<
TElectronicArchiveDetail
>
getDetailInfoById
(
String
id
)
{
TElectronicArchiveDetail
detail
=
baseMapper
.
selectById
(
id
);
if
(
Common
.
isEmpty
(
detail
))
{
return
R
.
failed
(
CommonConstants
.
NO_DATA_TO_HANDLE
);
}
// 查询该明细关联的所有任务
List
<
TTaskArchiveRelation
>
relations
=
relationService
.
list
(
Wrappers
.<
TTaskArchiveRelation
>
lambdaQuery
()
.
eq
(
TTaskArchiveRelation:
:
getArchiveDetailId
,
id
));
if
(
CollUtil
.
isEmpty
(
relations
))
{
log
.
info
(
"电子档案明细没有关联的任务,明细ID:{}"
,
id
);
return
R
.
ok
(
detail
);
}
// 按任务分组组织附件信息
List
<
TaskAttachmentGroupVO
>
taskGroups
=
new
ArrayList
<>();
for
(
TTaskArchiveRelation
relation
:
relations
)
{
// 查询任务信息
TElectronicArchiveTask
task
=
taskService
.
getById
(
relation
.
getTaskId
());
if
(
task
==
null
||
!
ArchiveConstants
.
TASK_STATUS_GENERATED
.
equals
(
task
.
getStatus
()))
{
// 任务不存在或未完成,跳过
continue
;
}
// 查询该任务上传的附件(domainId为明细ID,附件是在处理ZIP时关联到明细的)
List
<
TAttaInfo
>
taskAttachments
=
attaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
lambdaQuery
()
.
eq
(
TAttaInfo:
:
getDomainId
,
id
)
.
eq
(
TAttaInfo:
:
getRelationType
,
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
)
.
eq
(
TAttaInfo:
:
getStatus
,
ArchiveConstants
.
ATTA_STATUS_ENABLED
));
if
(
CollUtil
.
isEmpty
(
taskAttachments
))
{
continue
;
}
// 按资料类型分组附件
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeMap
=
new
LinkedHashMap
<>();
for
(
TAttaInfo
atta
:
taskAttachments
)
{
// 从附件路径中提取资料类型
// 路径格式:项目编码-姓名-身份证号/资料类型/文件名
String
materialType
=
extractMaterialTypeFromPath
(
atta
.
getAttaSrc
());
if
(
StrUtil
.
isBlank
(
materialType
))
{
materialType
=
"其他"
;
}
// 生成附件访问URL
URL
url
=
ossUtil
.
getObjectUrl
(
"yf-hr-efile-source"
,
atta
.
getAttaSrc
());
atta
.
setAttaUrl
(
url
.
toString
());
// 按资料类型分组
materialTypeMap
.
computeIfAbsent
(
materialType
,
k
->
new
ArrayList
<>()).
add
(
atta
);
}
// 创建任务附件分组VO
TaskAttachmentGroupVO
groupVO
=
new
TaskAttachmentGroupVO
();
groupVO
.
setTaskId
(
task
.
getId
());
groupVO
.
setTaskCode
(
task
.
getTaskCode
());
// 设置创建人和创建时间
String
createUser
=
task
.
getCreateName
();
if
(
StrUtil
.
isBlank
(
createUser
))
{
createUser
=
task
.
getCreateBy
();
}
groupVO
.
setCreateUser
(
createUser
);
groupVO
.
setCreateTime
(
task
.
getCreateTime
());
groupVO
.
setMaterialTypeAttachments
(
materialTypeMap
);
taskGroups
.
add
(
groupVO
);
}
// 按上传时间倒序排序(最新的在前面)
taskGroups
.
sort
((
g1
,
g2
)
->
g2
.
getCreateTime
().
compareTo
(
g1
.
getCreateTime
()));
detail
.
setTaskAttachmentGroups
(
taskGroups
);
return
R
.
ok
(
detail
);
}
/**
* 从附件路径中提取资料类型
* 路径格式:项目编码-姓名-身份证号/资料类型/文件名
*
* @param attaSrc 附件路径
* @return 资料类型
*/
private
String
extractMaterialTypeFromPath
(
String
attaSrc
)
{
if
(
StrUtil
.
isBlank
(
attaSrc
))
{
return
""
;
}
try
{
// 按/分割路径
String
[]
parts
=
attaSrc
.
split
(
"/"
);
if
(
parts
.
length
>=
2
)
{
// 第二部分应该是资料类型
String
materialType
=
parts
[
parts
.
length
-
2
];
// 验证是否是有效的资料类型
if
(
ArchiveConstants
.
MATERIAL_TYPE_STOCK
.
equals
(
materialType
)
||
ArchiveConstants
.
MATERIAL_TYPE_NEW
.
equals
(
materialType
)
||
ArchiveConstants
.
MATERIAL_TYPE_RENEW
.
equals
(
materialType
)
||
ArchiveConstants
.
MATERIAL_TYPE_LEAVE
.
equals
(
materialType
))
{
return
materialType
;
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"从附件路径提取资料类型失败,路径:{}"
,
attaSrc
,
e
);
}
return
""
;
}
/**
* 批量下载电子档案
*
* @param requestList 下载请求列表
* @param response HTTP响应
* @author huych
* @date 2025-12-17
*/
@Override
public
void
batchDownloadArchives
(
List
<
ArchiveBatchDownloadRequestVO
>
requestList
,
HttpServletResponse
response
)
{
log
.
info
(
"开始批量下载电子档案,请求数量:{}"
,
requestList
.
size
());
// 反馈列表
List
<
ArchiveDownloadFeedbackVO
>
feedbackList
=
new
ArrayList
<>();
// 用于存储需要下载的档案及其附件
Map
<
String
,
ArchiveDownloadInfo
>
downloadMap
=
new
LinkedHashMap
<>();
try
{
// 1. 校验请求并查询档案信息
for
(
ArchiveBatchDownloadRequestVO
request
:
requestList
)
{
try
{
validateAndPrepareDownload
(
request
,
downloadMap
,
feedbackList
);
}
catch
(
Exception
e
)
{
log
.
error
(
"处理下载请求失败,姓名:{},身份证:{},项目编码:{}"
,
request
.
getEmpName
(),
request
.
getEmpIdcard
(),
request
.
getDeptNo
(),
e
);
feedbackList
.
add
(
createFeedbackVO
(
request
,
"系统异常:"
+
e
.
getMessage
()));
}
}
// 2. 设置响应头
String
fileName
=
"电子档案批量下载_"
+
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmss"
))
+
".zip"
;
response
.
setContentType
(
"application/zip"
);
response
.
setCharacterEncoding
(
"UTF-8"
);
response
.
setHeader
(
CommonConstants
.
CONTENT_DISPOSITION
,
"attachment; filename="
+
URLEncoder
.
encode
(
fileName
,
"UTF-8"
));
// 3. 创建ZIP输出流
try
(
ZipOutputStream
zipOut
=
new
ZipOutputStream
(
response
.
getOutputStream
()))
{
// 4. 下载并打包档案文件
for
(
Map
.
Entry
<
String
,
ArchiveDownloadInfo
>
entry
:
downloadMap
.
entrySet
())
{
String
folderName
=
entry
.
getKey
();
ArchiveDownloadInfo
downloadInfo
=
entry
.
getValue
();
try
{
downloadArchiveFiles
(
zipOut
,
folderName
,
downloadInfo
);
// 更新反馈状态为成功
for
(
ArchiveDownloadFeedbackVO
feedback
:
feedbackList
)
{
if
(
feedback
.
getEmpName
().
equals
(
downloadInfo
.
getDetail
().
getEmpName
())
&&
feedback
.
getEmpIdcard
().
equals
(
downloadInfo
.
getDetail
().
getEmpIdcard
())
&&
feedback
.
getDeptNo
().
equals
(
downloadInfo
.
getDetail
().
getDeptNo
())
&&
feedback
.
getMaterialType
().
equals
(
downloadInfo
.
getMaterialType
()))
{
feedback
.
setDownloadStatus
(
"成功"
);
feedback
.
setFailReason
(
""
);
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"下载档案文件失败,文件夹:{}"
,
folderName
,
e
);
// 更新反馈状态为失败
for
(
ArchiveDownloadFeedbackVO
feedback
:
feedbackList
)
{
if
(
feedback
.
getEmpName
().
equals
(
downloadInfo
.
getDetail
().
getEmpName
())
&&
feedback
.
getEmpIdcard
().
equals
(
downloadInfo
.
getDetail
().
getEmpIdcard
())
&&
feedback
.
getDeptNo
().
equals
(
downloadInfo
.
getDetail
().
getDeptNo
())
&&
feedback
.
getMaterialType
().
equals
(
downloadInfo
.
getMaterialType
()))
{
feedback
.
setDownloadStatus
(
"失败"
);
feedback
.
setFailReason
(
"下载文件失败:"
+
e
.
getMessage
());
}
}
}
}
// 5. 生成并添加反馈Excel表
addFeedbackExcel
(
zipOut
,
feedbackList
);
zipOut
.
finish
();
log
.
info
(
"电子档案批量下载完成"
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"批量下载电子档案失败"
,
e
);
throw
new
RuntimeException
(
"批量下载失败:"
+
e
.
getMessage
(),
e
);
}
}
/**
* 校验请求并准备下载信息
*
* @param request 下载请求
* @param downloadMap 下载信息Map
* @param feedbackList 反馈列表
*/
private
void
validateAndPrepareDownload
(
ArchiveBatchDownloadRequestVO
request
,
Map
<
String
,
ArchiveDownloadInfo
>
downloadMap
,
List
<
ArchiveDownloadFeedbackVO
>
feedbackList
)
{
// 1. 根据姓名、身份证、项目编码、项目名称查询电子档案明细
LambdaQueryWrapper
<
TElectronicArchiveDetail
>
wrapper
=
Wrappers
.<
TElectronicArchiveDetail
>
lambdaQuery
()
.
eq
(
TElectronicArchiveDetail:
:
getEmpName
,
request
.
getEmpName
())
.
eq
(
TElectronicArchiveDetail:
:
getEmpIdcard
,
request
.
getEmpIdcard
())
.
eq
(
TElectronicArchiveDetail:
:
getDeptNo
,
request
.
getDeptNo
())
.
eq
(
ArchiveConstants
.
DETAIL_STATUS_ENABLED
.
equals
(
ArchiveConstants
.
DETAIL_STATUS_ENABLED
),
TElectronicArchiveDetail:
:
getStatus
,
ArchiveConstants
.
DETAIL_STATUS_ENABLED
);
// 如果项目名称不为空,添加项目名称条件
if
(
StrUtil
.
isNotBlank
(
request
.
getDeptName
()))
{
wrapper
.
eq
(
TElectronicArchiveDetail:
:
getDeptName
,
request
.
getDeptName
());
}
// 查询档案明细
TElectronicArchiveDetail
detail
=
baseMapper
.
selectOne
(
wrapper
);
// 2. 如果未找到档案,添加失败反馈
if
(
Common
.
isEmpty
(
detail
))
{
feedbackList
.
add
(
createFeedbackVO
(
request
,
"没找到这个人和项目对应的信息"
));
return
;
}
// 3. 判断是否下载所有资料类型
boolean
downloadAllTypes
=
StrUtil
.
isBlank
(
request
.
getMaterialType
());
if
(
downloadAllTypes
)
{
// 资料类型为空,下载该人员该项目下所有资料类型
log
.
info
(
"资料类型为空,将下载该人员该项目下所有资料类型,姓名:{},身份证:{},项目编码:{}"
,
request
.
getEmpName
(),
request
.
getEmpIdcard
(),
request
.
getDeptNo
());
// 查询该明细下所有可用附件
List
<
TAttaInfo
>
allAttaList
=
attaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
lambdaQuery
()
.
eq
(
TAttaInfo:
:
getDomainId
,
detail
.
getId
())
.
eq
(
TAttaInfo:
:
getRelationType
,
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
)
.
eq
(
TAttaInfo:
:
getStatus
,
ArchiveConstants
.
ATTA_STATUS_ENABLED
));
if
(
CollUtil
.
isEmpty
(
allAttaList
))
{
feedbackList
.
add
(
createFeedbackVO
(
request
,
"该人员在此项目下没有可用的附件"
));
return
;
}
// 构建文件夹名称:项目编码-姓名-身份证
String
folderName
=
detail
.
getDeptNo
()
+
"-"
+
detail
.
getEmpName
()
+
"-"
+
detail
.
getEmpIdcard
();
// 按资料类型分组附件
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeAttaMap
=
new
LinkedHashMap
<>();
for
(
TAttaInfo
atta
:
allAttaList
)
{
String
materialType
=
extractMaterialTypeFromPath
(
atta
.
getAttaSrc
());
if
(
StrUtil
.
isBlank
(
materialType
))
{
materialType
=
"其他"
;
}
materialTypeAttaMap
.
computeIfAbsent
(
materialType
,
k
->
new
ArrayList
<>()).
add
(
atta
);
}
// 添加到下载Map
ArchiveDownloadInfo
downloadInfo
=
downloadMap
.
get
(
folderName
);
if
(
downloadInfo
==
null
)
{
downloadInfo
=
new
ArchiveDownloadInfo
();
downloadInfo
.
setDetail
(
detail
);
downloadInfo
.
setMaterialTypeAttaMap
(
materialTypeAttaMap
);
downloadMap
.
put
(
folderName
,
downloadInfo
);
}
else
{
// 合并资料类型附件
downloadInfo
.
getMaterialTypeAttaMap
().
putAll
(
materialTypeAttaMap
);
}
downloadInfo
.
setMaterialType
(
"全部资料类型"
);
// 添加成功的反馈
ArchiveBatchDownloadRequestVO
feedbackRequest
=
new
ArchiveBatchDownloadRequestVO
();
feedbackRequest
.
setEmpName
(
request
.
getEmpName
());
feedbackRequest
.
setEmpIdcard
(
request
.
getEmpIdcard
());
feedbackRequest
.
setDeptNo
(
request
.
getDeptNo
());
feedbackRequest
.
setDeptName
(
request
.
getDeptName
());
feedbackRequest
.
setMaterialType
(
"全部资料类型"
);
feedbackList
.
add
(
createSuccessFeedbackVO
(
feedbackRequest
));
}
else
{
// 下载指定资料类型
// 检查资料类型是否匹配(支持多个资料类型,用逗号分隔)
if
(
StrUtil
.
isBlank
(
detail
.
getMaterialType
())
||
!
detail
.
getMaterialType
().
contains
(
request
.
getMaterialType
()))
{
feedbackList
.
add
(
createFeedbackVO
(
request
,
"该人员在此项目下没有【"
+
request
.
getMaterialType
()
+
"】类型的资料"
));
return
;
}
// 查询该明细下指定资料类型的附件(状态为可用)
List
<
TAttaInfo
>
attaList
=
attaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
lambdaQuery
()
.
eq
(
TAttaInfo:
:
getDomainId
,
detail
.
getId
())
.
eq
(
TAttaInfo:
:
getRelationType
,
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
)
.
eq
(
TAttaInfo:
:
getStatus
,
ArchiveConstants
.
ATTA_STATUS_ENABLED
)
.
like
(
TAttaInfo:
:
getAttaSrc
,
request
.
getMaterialType
()));
// 附件路径中包含资料类型
// 如果没有附件,添加失败反馈
if
(
CollUtil
.
isEmpty
(
attaList
))
{
feedbackList
.
add
(
createFeedbackVO
(
request
,
"该资料类型下没有可用的附件"
));
return
;
}
// 构建文件夹名称:项目编码-姓名-身份证
String
folderName
=
detail
.
getDeptNo
()
+
"-"
+
detail
.
getEmpName
()
+
"-"
+
detail
.
getEmpIdcard
();
// 添加到下载Map
ArchiveDownloadInfo
downloadInfo
=
downloadMap
.
get
(
folderName
);
if
(
downloadInfo
==
null
)
{
downloadInfo
=
new
ArchiveDownloadInfo
();
downloadInfo
.
setDetail
(
detail
);
downloadInfo
.
setMaterialTypeAttaMap
(
new
HashMap
<>());
downloadMap
.
put
(
folderName
,
downloadInfo
);
}
// 按资料类型分组附件
if
(!
downloadInfo
.
getMaterialTypeAttaMap
().
containsKey
(
request
.
getMaterialType
()))
{
downloadInfo
.
getMaterialTypeAttaMap
().
put
(
request
.
getMaterialType
(),
attaList
);
}
downloadInfo
.
setMaterialType
(
request
.
getMaterialType
());
// 添加成功的反馈(状态暂时为"处理中",实际下载完成后更新)
feedbackList
.
add
(
createSuccessFeedbackVO
(
request
));
}
}
/**
* 下载档案文件到ZIP
*
* @param zipOut ZIP输出流
* @param folderName 文件夹名称
* @param downloadInfo 下载信息
*/
private
void
downloadArchiveFiles
(
ZipOutputStream
zipOut
,
String
folderName
,
ArchiveDownloadInfo
downloadInfo
)
throws
Exception
{
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeAttaMap
=
downloadInfo
.
getMaterialTypeAttaMap
();
// 遍历每个资料类型
for
(
Map
.
Entry
<
String
,
List
<
TAttaInfo
>>
entry
:
materialTypeAttaMap
.
entrySet
())
{
String
materialType
=
entry
.
getKey
();
List
<
TAttaInfo
>
attaList
=
entry
.
getValue
();
// 创建二级文件夹:资料类型
String
subFolderPath
=
folderName
+
"/"
+
materialType
+
"/"
;
// 准备OSS对象Bean列表
List
<
OSSObjectBean
>
ossObjectList
=
new
ArrayList
<>();
for
(
TAttaInfo
atta
:
attaList
)
{
OSSObjectBean
bean
=
new
OSSObjectBean
();
bean
.
setKey
(
atta
.
getAttaSrc
());
// OSS文件路径
bean
.
setName
(
subFolderPath
+
atta
.
getAttaName
());
// ZIP中的完整路径
ossObjectList
.
add
(
bean
);
}
// 批量下载文件到ZIP
if
(
CollUtil
.
isNotEmpty
(
ossObjectList
))
{
ossUtil
.
getObjectZip
(
"yf-hr-efile-source"
,
ossObjectList
,
zipOut
);
}
}
}
/**
* 添加反馈Excel到ZIP
*
* @param zipOut ZIP输出流
* @param feedbackList 反馈列表
*/
private
void
addFeedbackExcel
(
ZipOutputStream
zipOut
,
List
<
ArchiveDownloadFeedbackVO
>
feedbackList
)
throws
IOException
{
try
{
// 创建Excel内存流
ByteArrayOutputStream
excelOut
=
new
ByteArrayOutputStream
();
// 使用EasyExcel写入Excel
EasyExcel
.
write
(
excelOut
,
ArchiveDownloadFeedbackVO
.
class
)
.
sheet
(
"下载结果反馈"
)
.
doWrite
(
feedbackList
);
// 添加Excel到ZIP
ZipEntry
excelEntry
=
new
ZipEntry
(
"下载结果反馈表.xlsx"
);
zipOut
.
putNextEntry
(
excelEntry
);
zipOut
.
write
(
excelOut
.
toByteArray
());
zipOut
.
closeEntry
();
excelOut
.
close
();
log
.
info
(
"反馈Excel添加成功,共{}条记录"
,
feedbackList
.
size
());
}
catch
(
Exception
e
)
{
log
.
error
(
"生成反馈Excel失败"
,
e
);
throw
new
IOException
(
"生成反馈Excel失败"
,
e
);
}
}
/**
* 创建失败反馈VO
*
* @param request 请求VO
* @param failReason 失败原因
* @return 反馈VO
*/
private
ArchiveDownloadFeedbackVO
createFeedbackVO
(
ArchiveBatchDownloadRequestVO
request
,
String
failReason
)
{
ArchiveDownloadFeedbackVO
feedback
=
new
ArchiveDownloadFeedbackVO
();
feedback
.
setEmpName
(
request
.
getEmpName
());
feedback
.
setEmpIdcard
(
request
.
getEmpIdcard
());
feedback
.
setDeptNo
(
request
.
getDeptNo
());
feedback
.
setDeptName
(
request
.
getDeptName
());
feedback
.
setMaterialType
(
request
.
getMaterialType
());
feedback
.
setDownloadStatus
(
"失败"
);
feedback
.
setFailReason
(
failReason
);
return
feedback
;
}
/**
* 创建成功反馈VO
*
* @param request 请求VO
* @return 反馈VO
*/
private
ArchiveDownloadFeedbackVO
createSuccessFeedbackVO
(
ArchiveBatchDownloadRequestVO
request
)
{
ArchiveDownloadFeedbackVO
feedback
=
new
ArchiveDownloadFeedbackVO
();
feedback
.
setEmpName
(
request
.
getEmpName
());
feedback
.
setEmpIdcard
(
request
.
getEmpIdcard
());
feedback
.
setDeptNo
(
request
.
getDeptNo
());
feedback
.
setDeptName
(
request
.
getDeptName
());
feedback
.
setMaterialType
(
request
.
getMaterialType
());
feedback
.
setDownloadStatus
(
"处理中"
);
feedback
.
setFailReason
(
""
);
return
feedback
;
}
/**
* 下载信息内部类
*/
private
static
class
ArchiveDownloadInfo
{
private
TElectronicArchiveDetail
detail
;
private
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeAttaMap
;
private
String
materialType
;
public
TElectronicArchiveDetail
getDetail
()
{
return
detail
;
}
public
void
setDetail
(
TElectronicArchiveDetail
detail
)
{
this
.
detail
=
detail
;
}
public
Map
<
String
,
List
<
TAttaInfo
>>
getMaterialTypeAttaMap
()
{
return
materialTypeAttaMap
;
}
public
void
setMaterialTypeAttaMap
(
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeAttaMap
)
{
this
.
materialTypeAttaMap
=
materialTypeAttaMap
;
}
public
String
getMaterialType
()
{
return
materialType
;
}
public
void
setMaterialType
(
String
materialType
)
{
this
.
materialType
=
materialType
;
}
}
/**
* 删除电子档案附件
* <p>
* 功能说明:
* 1. 校验请求参数(明细ID、任务ID、资料类型、附件ID列表)
* 2. 校验附件是否属于指定的明细、任务和资料类型
* 3. 将附件状态更新为不可用(逻辑删除)
* 4. 同时删除OSS上的文件
* 5. 如果该资料类型下的所有附件都被删除,则从明细的资料类型字段中移除该类型
* </p>
*
* @param request 删除请求
* @return 删除结果
* @author huych
* @date 2025-12-17
*/
@Override
public
R
<
String
>
deleteArchiveAttachments
(
ArchiveAttachmentDeleteRequestVO
request
)
{
log
.
info
(
"开始删除电子档案附件,明细ID:{},任务ID:{},资料类型:{},附件数量:{}"
,
request
.
getDetailId
(),
request
.
getTaskId
(),
request
.
getMaterialType
(),
request
.
getAttachmentIds
().
size
());
try
{
// 1. 校验明细是否存在
TElectronicArchiveDetail
detail
=
baseMapper
.
selectById
(
request
.
getDetailId
());
if
(
Common
.
isEmpty
(
detail
))
{
return
R
.
failed
(
"电子档案明细不存在"
);
}
// 2. 校验任务是否存在
TElectronicArchiveTask
task
=
taskService
.
getById
(
request
.
getTaskId
());
if
(
task
==
null
)
{
return
R
.
failed
(
"任务不存在"
);
}
// 3. 校验任务和明细的关联关系
LambdaQueryWrapper
<
TTaskArchiveRelation
>
relationWrapper
=
Wrappers
.<
TTaskArchiveRelation
>
lambdaQuery
()
.
eq
(
TTaskArchiveRelation:
:
getTaskId
,
request
.
getTaskId
())
.
eq
(
TTaskArchiveRelation:
:
getArchiveDetailId
,
request
.
getDetailId
());
TTaskArchiveRelation
relation
=
relationService
.
getOne
(
relationWrapper
);
if
(
relation
==
null
)
{
return
R
.
failed
(
"任务和档案明细没有关联关系"
);
}
// 4. 校验资料类型是否有效
if
(!
isValidMaterialType
(
request
.
getMaterialType
()))
{
return
R
.
failed
(
"资料类型不正确,必须为:存量、新签、续签、离职"
);
}
// 5. 查询要删除的附件
List
<
TAttaInfo
>
attachments
=
attaInfoService
.
listByIds
(
request
.
getAttachmentIds
());
if
(
CollUtil
.
isEmpty
(
attachments
))
{
return
R
.
failed
(
"附件不存在"
);
}
// 6. 校验附件是否都属于该明细
for
(
TAttaInfo
atta
:
attachments
)
{
if
(!
request
.
getDetailId
().
equals
(
atta
.
getDomainId
()))
{
return
R
.
failed
(
"附件【"
+
atta
.
getAttaName
()
+
"】不属于该档案明细"
);
}
// 校验附件关系类型是否为ZIP附件
if
(!
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
.
equals
(
atta
.
getRelationType
()))
{
return
R
.
failed
(
"附件【"
+
atta
.
getAttaName
()
+
"】不是电子档案附件"
);
}
// 校验附件是否属于指定的资料类型(从路径中提取)
String
materialType
=
extractMaterialTypeFromPath
(
atta
.
getAttaSrc
());
if
(!
request
.
getMaterialType
().
equals
(
materialType
))
{
return
R
.
failed
(
"附件【"
+
atta
.
getAttaName
()
+
"】不属于资料类型【"
+
request
.
getMaterialType
()
+
"】"
);
}
}
// 7. 逻辑删除附件(将状态更新为不可用)
int
successCount
=
0
;
int
failCount
=
0
;
StringBuilder
failReasons
=
new
StringBuilder
();
for
(
TAttaInfo
atta
:
attachments
)
{
try
{
// 更新附件状态为不可用
atta
.
setStatus
(
ArchiveConstants
.
ATTA_STATUS_DISABLED
);
boolean
updated
=
attaInfoService
.
updateById
(
atta
);
if
(
updated
)
{
// 删除OSS文件
try
{
ossUtil
.
deleteObject
(
"yf-hr-efile-source"
,
atta
.
getAttaSrc
());
successCount
++;
log
.
info
(
"删除附件成功,附件ID:{},文件名:{}"
,
atta
.
getId
(),
atta
.
getAttaName
());
}
catch
(
Exception
e
)
{
log
.
error
(
"删除OSS文件失败,附件ID:{},路径:{}"
,
atta
.
getId
(),
atta
.
getAttaSrc
(),
e
);
// OSS删除失败不影响整体流程,已经逻辑删除了
successCount
++;
}
}
else
{
failCount
++;
failReasons
.
append
(
atta
.
getAttaName
()).
append
(
";"
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"删除附件失败,附件ID:{}"
,
atta
.
getId
(),
e
);
failCount
++;
failReasons
.
append
(
atta
.
getAttaName
()).
append
(
";"
);
}
}
// 8. 检查该资料类型下是否还有其他可用附件
LambdaQueryWrapper
<
TAttaInfo
>
attaWrapper
=
Wrappers
.<
TAttaInfo
>
lambdaQuery
()
.
eq
(
TAttaInfo:
:
getDomainId
,
request
.
getDetailId
())
.
eq
(
TAttaInfo:
:
getRelationType
,
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
)
.
eq
(
TAttaInfo:
:
getStatus
,
ArchiveConstants
.
ATTA_STATUS_ENABLED
)
.
like
(
TAttaInfo:
:
getAttaSrc
,
"/"
+
request
.
getMaterialType
()
+
"/"
);
long
remainingCount
=
attaInfoService
.
count
(
attaWrapper
);
// 9. 如果该资料类型下没有附件了,从明细的资料类型字段中移除
if
(
remainingCount
==
0
)
{
updateDetailMaterialTypeAfterDelete
(
detail
,
request
.
getMaterialType
());
}
// 10. 返回结果
String
resultMsg
=
String
.
format
(
"删除完成,成功:%d个,失败:%d个"
,
successCount
,
failCount
);
if
(
failCount
>
0
)
{
resultMsg
+=
"。失败的附件:"
+
failReasons
.
toString
();
}
log
.
info
(
"删除电子档案附件完成,明细ID:{},结果:{}"
,
request
.
getDetailId
(),
resultMsg
);
return
R
.
ok
(
null
,
resultMsg
);
}
catch
(
Exception
e
)
{
log
.
error
(
"删除电子档案附件失败,明细ID:{}"
,
request
.
getDetailId
(),
e
);
return
R
.
failed
(
"删除失败:"
+
e
.
getMessage
());
}
}
/**
* 判断是否是有效的资料类型
*/
private
boolean
isValidMaterialType
(
String
typeName
)
{
return
ArchiveConstants
.
MATERIAL_TYPE_STOCK
.
equals
(
typeName
)
||
ArchiveConstants
.
MATERIAL_TYPE_NEW
.
equals
(
typeName
)
||
ArchiveConstants
.
MATERIAL_TYPE_RENEW
.
equals
(
typeName
)
||
ArchiveConstants
.
MATERIAL_TYPE_LEAVE
.
equals
(
typeName
);
}
/**
* 删除附件后更新明细表的资料类型
* 从资料类型字段中移除指定的资料类型
*
* @param detail 档案明细
* @param removedMaterialType 要移除的资料类型
*/
private
void
updateDetailMaterialTypeAfterDelete
(
TElectronicArchiveDetail
detail
,
String
removedMaterialType
)
{
try
{
if
(
StrUtil
.
isBlank
(
detail
.
getMaterialType
()))
{
return
;
}
// 解析资料类型列表
List
<
String
>
materialTypes
=
new
ArrayList
<>(
Arrays
.
asList
(
detail
.
getMaterialType
().
split
(
","
)));
// 移除指定的资料类型
materialTypes
.
remove
(
removedMaterialType
);
// 更新明细
if
(
materialTypes
.
isEmpty
())
{
// 如果所有资料类型都被删除了,将状态改为不可用
detail
.
setMaterialType
(
""
);
detail
.
setStatus
(
ArchiveConstants
.
DETAIL_STATUS_DISABLED
);
}
else
{
detail
.
setMaterialType
(
String
.
join
(
","
,
materialTypes
));
}
baseMapper
.
updateById
(
detail
);
log
.
info
(
"更新档案明细资料类型成功,明细ID:{},新的资料类型:{}"
,
detail
.
getId
(),
detail
.
getMaterialType
());
}
catch
(
Exception
e
)
{
log
.
error
(
"更新档案明细资料类型失败,明细ID:{}"
,
detail
.
getId
(),
e
);
}
}
/**
* 勾选导出电子档案
* <p>
* 功能说明:
* 1. 根据明细ID、任务ID、资料类型列表导出指定的附件
* 2. 导出格式与批量下载功能保持一致
* 3. 一级文件夹:项目编码-姓名-身份证
* 4. 二级文件夹:资料类型,该文件夹下为具体附件
* 5. 压缩包命名规则为:电子档案勾选导出_时间戳.zip
* 6. 只导出status为可用(0)的附件
* </p>
*
* @param requestList 导出请求列表
* @param response HTTP响应
* @author huych
* @date 2025-12-17
*/
@Override
public
void
selectedExportArchives
(
List
<
ArchiveSelectedExportRequestVO
>
requestList
,
HttpServletResponse
response
)
{
log
.
info
(
"开始勾选导出电子档案,请求数量:{}"
,
requestList
.
size
());
// 反馈列表
List
<
ArchiveDownloadFeedbackVO
>
feedbackList
=
new
ArrayList
<>();
// 用于存储需要导出的档案及其附件
Map
<
String
,
ArchiveDownloadInfo
>
downloadMap
=
new
LinkedHashMap
<>();
try
{
// 1. 校验请求并查询档案信息
for
(
ArchiveSelectedExportRequestVO
request
:
requestList
)
{
try
{
validateAndPrepareSelectedExport
(
request
,
downloadMap
,
feedbackList
);
}
catch
(
Exception
e
)
{
log
.
error
(
"处理勾选导出请求失败,明细ID:{},任务ID:{}"
,
request
.
getDetailId
(),
request
.
getTaskId
(),
e
);
feedbackList
.
add
(
createSelectedExportFeedbackVO
(
request
,
"系统异常:"
+
e
.
getMessage
()));
}
}
// 2. 检查是否有可导出的档案
if
(
downloadMap
.
isEmpty
())
{
log
.
warn
(
"没有可导出的档案"
);
response
.
setContentType
(
"application/json;charset=UTF-8"
);
response
.
getWriter
().
write
(
"{\"code\":1,\"msg\":\"没有可导出的档案\"}"
);
return
;
}
// 3. 设置响应头
String
fileName
=
"电子档案勾选导出_"
+
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmss"
))
+
".zip"
;
response
.
setContentType
(
"application/zip"
);
response
.
setCharacterEncoding
(
"UTF-8"
);
response
.
setHeader
(
CommonConstants
.
CONTENT_DISPOSITION
,
"attachment; filename="
+
URLEncoder
.
encode
(
fileName
,
"UTF-8"
));
// 4. 创建ZIP输出流
try
(
ZipOutputStream
zipOut
=
new
ZipOutputStream
(
response
.
getOutputStream
()))
{
// 5. 下载并打包档案文件
for
(
Map
.
Entry
<
String
,
ArchiveDownloadInfo
>
entry
:
downloadMap
.
entrySet
())
{
String
folderName
=
entry
.
getKey
();
ArchiveDownloadInfo
downloadInfo
=
entry
.
getValue
();
try
{
downloadArchiveFiles
(
zipOut
,
folderName
,
downloadInfo
);
// 更新反馈状态为成功
updateFeedbackStatus
(
feedbackList
,
downloadInfo
,
"成功"
,
""
);
}
catch
(
Exception
e
)
{
log
.
error
(
"导出档案文件失败,文件夹:{}"
,
folderName
,
e
);
// 更新反馈状态为失败
updateFeedbackStatus
(
feedbackList
,
downloadInfo
,
"失败"
,
"导出文件失败:"
+
e
.
getMessage
());
}
}
// 6. 生成并添加反馈Excel表
addFeedbackExcel
(
zipOut
,
feedbackList
);
zipOut
.
finish
();
log
.
info
(
"电子档案勾选导出完成"
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"勾选导出电子档案失败"
,
e
);
throw
new
RuntimeException
(
"勾选导出失败:"
+
e
.
getMessage
(),
e
);
}
}
/**
* 校验请求并准备勾选导出信息
*
* @param request 导出请求
* @param downloadMap 下载信息Map
* @param feedbackList 反馈列表
*/
private
void
validateAndPrepareSelectedExport
(
ArchiveSelectedExportRequestVO
request
,
Map
<
String
,
ArchiveDownloadInfo
>
downloadMap
,
List
<
ArchiveDownloadFeedbackVO
>
feedbackList
)
{
// 1. 校验明细是否存在
TElectronicArchiveDetail
detail
=
baseMapper
.
selectById
(
request
.
getDetailId
());
if
(
Common
.
isEmpty
(
detail
))
{
feedbackList
.
add
(
createSelectedExportFeedbackVO
(
request
,
"电子档案明细不存在"
));
return
;
}
// 2. 校验任务是否存在
TElectronicArchiveTask
task
=
taskService
.
getById
(
request
.
getTaskId
());
if
(
task
==
null
)
{
feedbackList
.
add
(
createSelectedExportFeedbackVO
(
request
,
"任务不存在"
));
return
;
}
// 3. 校验任务和明细的关联关系
LambdaQueryWrapper
<
TTaskArchiveRelation
>
relationWrapper
=
Wrappers
.<
TTaskArchiveRelation
>
lambdaQuery
()
.
eq
(
TTaskArchiveRelation:
:
getTaskId
,
request
.
getTaskId
())
.
eq
(
TTaskArchiveRelation:
:
getArchiveDetailId
,
request
.
getDetailId
());
TTaskArchiveRelation
relation
=
relationService
.
getOne
(
relationWrapper
);
if
(
relation
==
null
)
{
feedbackList
.
add
(
createSelectedExportFeedbackVO
(
request
,
"任务和档案明细没有关联关系"
));
return
;
}
// 4. 校验资料类型是否为空
if
(
CollUtil
.
isEmpty
(
request
.
getMaterialTypes
()))
{
feedbackList
.
add
(
createSelectedExportFeedbackVO
(
request
,
"资料类型列表不能为空"
));
return
;
}
// 5. 构建文件夹名称:项目编码-姓名-身份证
String
folderName
=
detail
.
getDeptNo
()
+
"-"
+
detail
.
getEmpName
()
+
"-"
+
detail
.
getEmpIdcard
();
// 6. 按资料类型查询附件
Map
<
String
,
List
<
TAttaInfo
>>
materialTypeAttaMap
=
new
LinkedHashMap
<>();
for
(
String
materialType
:
request
.
getMaterialTypes
())
{
// 校验资料类型是否有效
if
(!
isValidMaterialType
(
materialType
))
{
log
.
warn
(
"资料类型无效,跳过:{}"
,
materialType
);
continue
;
}
// 查询该明细下该任务的指定资料类型的附件
// 通过附件路径匹配资料类型和任务
List
<
TAttaInfo
>
attaList
=
attaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
lambdaQuery
()
.
eq
(
TAttaInfo:
:
getDomainId
,
request
.
getDetailId
())
.
eq
(
TAttaInfo:
:
getRelationType
,
ArchiveConstants
.
ATTA_RELATION_TYPE_ZIP
)
.
eq
(
TAttaInfo:
:
getStatus
,
ArchiveConstants
.
ATTA_STATUS_ENABLED
)
.
like
(
TAttaInfo:
:
getAttaSrc
,
materialType
));
// 附件路径中包含资料类型
// 过滤附件:只保留属于指定任务的附件
// 方法:通过创建时间范围过滤(任务创建时间之后的附件)
List
<
TAttaInfo
>
taskAttaList
=
new
ArrayList
<>();
for
(
TAttaInfo
atta
:
attaList
)
{
// 简单判断:附件创建时间在任务创建时间之后
if
(
atta
.
getCreateTime
()
!=
null
&&
task
.
getCreateTime
()
!=
null
&&
!
atta
.
getCreateTime
().
isBefore
(
task
.
getCreateTime
()))
{
taskAttaList
.
add
(
atta
);
}
}
// 如果该资料类型下有附件,添加到Map中
if
(
CollUtil
.
isNotEmpty
(
taskAttaList
))
{
materialTypeAttaMap
.
put
(
materialType
,
taskAttaList
);
// 添加成功的反馈
feedbackList
.
add
(
createSelectedExportSuccessFeedbackVO
(
detail
,
task
,
materialType
));
}
else
{
// 添加失败的反馈
log
.
warn
(
"该资料类型下没有可用的附件,明细ID:{},任务ID:{},资料类型:{}"
,
request
.
getDetailId
(),
request
.
getTaskId
(),
materialType
);
feedbackList
.
add
(
createSelectedExportFeedbackVOWithDetail
(
detail
,
task
,
materialType
,
"该资料类型下没有可用的附件"
));
}
}
// 7. 如果有可导出的附件,添加到下载Map
if
(!
materialTypeAttaMap
.
isEmpty
())
{
ArchiveDownloadInfo
downloadInfo
=
downloadMap
.
get
(
folderName
);
if
(
downloadInfo
==
null
)
{
downloadInfo
=
new
ArchiveDownloadInfo
();
downloadInfo
.
setDetail
(
detail
);
downloadInfo
.
setMaterialTypeAttaMap
(
materialTypeAttaMap
);
downloadMap
.
put
(
folderName
,
downloadInfo
);
}
else
{
// 合并资料类型附件
downloadInfo
.
getMaterialTypeAttaMap
().
putAll
(
materialTypeAttaMap
);
}
// 设置资料类型列表
downloadInfo
.
setMaterialType
(
String
.
join
(
","
,
materialTypeAttaMap
.
keySet
()));
}
}
/**
* 创建勾选导出失败反馈VO
*
* @param request 请求VO
* @param failReason 失败原因
* @return 反馈VO
*/
private
ArchiveDownloadFeedbackVO
createSelectedExportFeedbackVO
(
ArchiveSelectedExportRequestVO
request
,
String
failReason
)
{
ArchiveDownloadFeedbackVO
feedback
=
new
ArchiveDownloadFeedbackVO
();
feedback
.
setEmpName
(
"未知"
);
feedback
.
setEmpIdcard
(
"未知"
);
feedback
.
setDeptNo
(
"未知"
);
feedback
.
setDeptName
(
"未知"
);
feedback
.
setMaterialType
(
request
.
getMaterialTypes
()
!=
null
?
String
.
join
(
","
,
request
.
getMaterialTypes
())
:
""
);
feedback
.
setDownloadStatus
(
"失败"
);
feedback
.
setFailReason
(
failReason
);
return
feedback
;
}
/**
* 创建勾选导出失败反馈VO(带明细和任务信息)
*
* @param detail 明细
* @param task 任务
* @param materialType 资料类型
* @param failReason 失败原因
* @return 反馈VO
*/
private
ArchiveDownloadFeedbackVO
createSelectedExportFeedbackVOWithDetail
(
TElectronicArchiveDetail
detail
,
TElectronicArchiveTask
task
,
String
materialType
,
String
failReason
)
{
ArchiveDownloadFeedbackVO
feedback
=
new
ArchiveDownloadFeedbackVO
();
feedback
.
setEmpName
(
detail
.
getEmpName
());
feedback
.
setEmpIdcard
(
detail
.
getEmpIdcard
());
feedback
.
setDeptNo
(
detail
.
getDeptNo
());
feedback
.
setDeptName
(
detail
.
getDeptName
());
feedback
.
setMaterialType
(
materialType
);
feedback
.
setDownloadStatus
(
"失败"
);
feedback
.
setFailReason
(
failReason
);
return
feedback
;
}
/**
* 创建勾选导出成功反馈VO
*
* @param detail 明细
* @param task 任务
* @param materialType 资料类型
* @return 反馈VO
*/
private
ArchiveDownloadFeedbackVO
createSelectedExportSuccessFeedbackVO
(
TElectronicArchiveDetail
detail
,
TElectronicArchiveTask
task
,
String
materialType
)
{
ArchiveDownloadFeedbackVO
feedback
=
new
ArchiveDownloadFeedbackVO
();
feedback
.
setEmpName
(
detail
.
getEmpName
());
feedback
.
setEmpIdcard
(
detail
.
getEmpIdcard
());
feedback
.
setDeptNo
(
detail
.
getDeptNo
());
feedback
.
setDeptName
(
detail
.
getDeptName
());
feedback
.
setMaterialType
(
materialType
);
feedback
.
setDownloadStatus
(
"处理中"
);
feedback
.
setFailReason
(
""
);
return
feedback
;
}
/**
* 更新反馈状态
*
* @param feedbackList 反馈列表
* @param downloadInfo 下载信息
* @param status 状态
* @param failReason 失败原因
*/
private
void
updateFeedbackStatus
(
List
<
ArchiveDownloadFeedbackVO
>
feedbackList
,
ArchiveDownloadInfo
downloadInfo
,
String
status
,
String
failReason
)
{
TElectronicArchiveDetail
detail
=
downloadInfo
.
getDetail
();
Set
<
String
>
materialTypes
=
downloadInfo
.
getMaterialTypeAttaMap
().
keySet
();
for
(
ArchiveDownloadFeedbackVO
feedback
:
feedbackList
)
{
if
(
feedback
.
getEmpName
().
equals
(
detail
.
getEmpName
())
&&
feedback
.
getEmpIdcard
().
equals
(
detail
.
getEmpIdcard
())
&&
feedback
.
getDeptNo
().
equals
(
detail
.
getDeptNo
())
&&
materialTypes
.
contains
(
feedback
.
getMaterialType
()))
{
feedback
.
setDownloadStatus
(
status
);
feedback
.
setFailReason
(
failReason
);
}
}
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/TElectronicArchiveTaskServiceImpl.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail
;
import
com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
import
com.yifu.cloud.plus.v1.batch.mapper.TElectronicArchiveTaskMapper
;
import
com.yifu.cloud.plus.v1.batch.service.TElectronicArchiveDetailService
;
import
com.yifu.cloud.plus.v1.batch.service.TElectronicArchiveTaskService
;
import
com.yifu.cloud.plus.v1.batch.service.TTaskArchiveRelationService
;
import
com.yifu.cloud.plus.v1.batch.vo.TElectronicArchiveTaskSearchVo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.log4j.Log4j2
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
/**
* 电子档案任务表
*
* @author huych
* @date 2025-12-17 11:03:07
*/
@Log4j2
@Service
@RequiredArgsConstructor
public
class
TElectronicArchiveTaskServiceImpl
extends
ServiceImpl
<
TElectronicArchiveTaskMapper
,
TElectronicArchiveTask
>
implements
TElectronicArchiveTaskService
{
private
final
TTaskArchiveRelationService
relationService
;
private
final
TElectronicArchiveDetailService
detailService
;
/**
* 电子档案任务表简单分页查询
* @param tElectronicArchiveTask 电子档案任务表
* @return
*/
@Override
public
IPage
<
TElectronicArchiveTask
>
getTElectronicArchiveTaskPage
(
Page
<
TElectronicArchiveTask
>
page
,
TElectronicArchiveTaskSearchVo
tElectronicArchiveTask
){
return
baseMapper
.
getTElectronicArchiveTaskPage
(
page
,
tElectronicArchiveTask
);
}
@Override
public
R
deleteTaskById
(
String
id
)
{
TElectronicArchiveTask
task
=
this
.
getById
(
id
);
if
(
task
==
null
)
{
return
R
.
failed
(
"任务不存在"
);
}
if
(!
CommonConstants
.
ZERO_STRING
.
equals
(
task
.
getStatus
()))
{
return
R
.
failed
(
"只有待上传状态的任务才可删除!"
);
}
baseMapper
.
deleteById
(
id
);
List
<
TTaskArchiveRelation
>
relationList
=
relationService
.
list
(
Wrappers
.<
TTaskArchiveRelation
>
query
().
lambda
()
.
eq
(
TTaskArchiveRelation:
:
getTaskId
,
id
));
if
(
Common
.
isNotNull
(
relationList
))
{
for
(
TTaskArchiveRelation
relation
:
relationList
)
{
//删除关联关系表
relationService
.
removeById
(
relation
.
getId
());
//删除电子档案明细表
detailService
.
remove
(
Wrappers
.<
TElectronicArchiveDetail
>
query
().
lambda
()
.
eq
(
TElectronicArchiveDetail:
:
getId
,
relation
.
getArchiveDetailId
()));
}
}
return
R
.
ok
();
}
}
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/TTaskArchiveRelationServiceImpl.java
0 → 100644
View file @
3ffe3bb0
package
com
.
yifu
.
cloud
.
plus
.
v1
.
batch
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation
;
import
com.yifu.cloud.plus.v1.batch.mapper.TTaskArchiveRelationMapper
;
import
com.yifu.cloud.plus.v1.batch.service.TTaskArchiveRelationService
;
import
lombok.extern.log4j.Log4j2
;
import
org.springframework.stereotype.Service
;
/**
* 电子档案上传任务和档案明细关系表
*
* @author huych
* @date 2025-12-17 11:02:01
*/
@Log4j2
@Service
public
class
TTaskArchiveRelationServiceImpl
extends
ServiceImpl
<
TTaskArchiveRelationMapper
,
TTaskArchiveRelation
>
implements
TTaskArchiveRelationService
{
/**
* 电子档案上传任务和档案明细关系表简单分页查询
* @param tTaskArchiveRelation 电子档案上传任务和档案明细关系表
* @return
*/
@Override
public
IPage
<
TTaskArchiveRelation
>
getTTaskArchiveRelationPage
(
Page
<
TTaskArchiveRelation
>
page
,
TTaskArchiveRelation
tTaskArchiveRelation
){
return
baseMapper
.
getTTaskArchiveRelationPage
(
page
,
tTaskArchiveRelation
);
}
}
yifu-batch/yifu-batch-biz/src/main/resources/mapper/SysConfigLimitMapper.xml
0 → 100644
View file @
3ffe3bb0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yifu.cloud.plus.v1.batch.mapper.SysConfigLimitMapper"
>
<resultMap
id=
"sysConfigLimitMap"
type=
"com.yifu.cloud.plus.v1.batch.entity.SysConfigLimit"
>
<id
property=
"id"
column=
"ID"
/>
<result
property=
"configKey"
column=
"CONFIG_KEY"
/>
<result
property=
"configValue"
column=
"CONFIG_VALUE"
/>
<result
property=
"remark"
column=
"REMARK"
/>
</resultMap>
<!-- 根据key获取value -->
<select
id=
"getSysConfigLimitByKey"
resultType=
"java.lang.Integer"
>
SELECT a.CONFIG_VALUE
FROM sys_config_limit a
where a.CONFIG_KEY = #{configKey} limit 1
</select>
</mapper>
yifu-batch/yifu-batch-biz/src/main/resources/mapper/TAttaInfoMapper.xml
0 → 100644
View file @
3ffe3bb0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yifu.cloud.plus.v1.batch.mapper.TAttaInfoMapper"
>
<resultMap
id=
"tAttaInfoMap"
type=
"com.yifu.cloud.plus.v1.batch.entity.TAttaInfo"
>
<id
property=
"id"
column=
"id"
/>
<result
property=
"attaName"
column=
"atta_name"
/>
<result
property=
"attaSrc"
column=
"atta_src"
/>
<result
property=
"attaSize"
column=
"atta_size"
/>
<result
property=
"attaType"
column=
"atta_type"
/>
<result
property=
"createBy"
column=
"create_by"
/>
<result
property=
"createTime"
column=
"create_time"
/>
<result
property=
"relationType"
column=
"relation_type"
/>
<result
property=
"domainId"
column=
"domain_id"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
a.id,
a.atta_name,
a.atta_src,
a.atta_size,
a.atta_type,
a.create_by,
a.create_time,
a.relation_type,
a.domain_id
</sql>
<sql
id=
"tAttaInfo_where"
>
<if
test=
"tAttaInfo != null"
>
<if
test=
"tAttaInfo.id != null and tAttaInfo.id.trim() != ''"
>
AND a.id = #{tAttaInfo.id}
</if>
<if
test=
"tAttaInfo.attaName != null and tAttaInfo.attaName.trim() != ''"
>
AND a.atta_name = #{tAttaInfo.attaName}
</if>
<if
test=
"tAttaInfo.attaSrc != null and tAttaInfo.attaSrc.trim() != ''"
>
AND a.atta_src = #{tAttaInfo.attaSrc}
</if>
<if
test=
"tAttaInfo.attaSize != null"
>
AND a.atta_size = #{tAttaInfo.attaSize}
</if>
<if
test=
"tAttaInfo.attaType != null and tAttaInfo.attaType.trim() != ''"
>
AND a.atta_type = #{tAttaInfo.attaType}
</if>
<if
test=
"tAttaInfo.createBy != null and tAttaInfo.createBy.trim() != ''"
>
AND a.create_by = #{tAttaInfo.createBy}
</if>
<if
test=
"tAttaInfo.createTime != null"
>
AND a.create_time = #{tAttaInfo.createTime}
</if>
<if
test=
"tAttaInfo.relationType != null and tAttaInfo.relationType.trim() != ''"
>
AND a.relation_type = #{tAttaInfo.relationType}
</if>
<if
test=
"tAttaInfo.domainId != null and tAttaInfo.domainId.trim() != ''"
>
AND a.domain_id = #{tAttaInfo.domainId}
</if>
</if>
</sql>
<!--tAttaInfo简单分页查询-->
<select
id=
"getTAttaInfoPage"
resultMap=
"tAttaInfoMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_atta_info a
<where>
1=1
<include
refid=
"tAttaInfo_where"
/>
</where>
</select>
<!--tAttaInfo 获取list-->
<select
id=
"getTAttaInfoList"
resultMap=
"tAttaInfoMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_atta_info a
<where>
1=1
<include
refid=
"tAttaInfo_where"
/>
</where>
</select>
<!--根据domainId 获取list-->
<select
id=
"getTAttaInfoListByDoMainId"
resultMap=
"tAttaInfoMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_atta_info a
where a.domain_id = #{domainId}
</select>
<select
id=
"getKeenAtta"
resultMap=
"tAttaInfoMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_atta_info a
<where>
1=1
<if
test=
"values != null and values.size() > 0"
>
and a.domain_id in
<foreach
collection=
"values"
item=
"param"
index=
"index"
open=
"("
close=
")"
separator=
","
>
#{param}
</foreach>
</if>
and a.create_time >= #{dayStart}
and a.relation_type in ("3","4")
</where>
</select>
<update
id=
"updateDomainId"
>
update t_atta_info
<trim
prefix=
"set"
suffixOverrides=
","
>
domain_id=#{domainId}
</trim>
WHERE
<if
test=
"ids != null and ids.size() > 0"
>
id in
<foreach
collection=
"ids"
item=
"param"
index=
"index"
open=
"("
close=
")"
separator=
","
>
#{param}
</foreach>
</if>
</update>
<select
id=
"getAttaByApplyId"
resultMap=
"tAttaInfoMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_atta_info a
where EXISTS (select 1 from m_salary_prova_atta b where b.SALARY_PROVA_ID = #{applyId} and a.id = b.ATTA_ID);
</select>
<delete
id=
"deleteByDomainId"
>
delete from t_atta_info where domain_id=#{domainId}
</delete>
<!-- 详档变简档,删除身份证、其他附件、签名之外的附件 -->
<delete
id=
"deleteByDomainIdExceptionCard"
>
delete from t_atta_info where domain_id=#{domainId} and relation_type not in ('9','24','27','21','22')
</delete>
<delete
id=
"deleteByDomainIdAndType"
>
delete from t_atta_info where domain_id=#{domainId} and relation_type = #{relationType}
</delete>
<delete
id=
"deleteByDomainIdAndOther"
>
delete from t_atta_info where domain_id=#{domainId} and relation_type not in ('0','2','26','27')
</delete>
<!-- 简档,仅删除身份证附件和(21(预入职申明签名);22(预入职确认签名);23(预入职pdf文) -->
<delete
id=
"deleteByDomainIdCard"
>
delete from t_atta_info where domain_id=#{domainId} and relation_type in ('9','24','21','22','23')
</delete>
<select
id=
"getAttInfoCountByParam"
resultType=
"java.lang.Integer"
>
SELECT
count(1)
from (select id from t_pre_emp_main where `STATUS`='4' and SOUR_TYPE='0'
and DEPT_NO = #{departNo}
and AUDIT_TIME >= #{startDate}
and AUDIT_TIME
<![CDATA[ <= ]]>
#{endDate}) a
LEFT JOIN (select * from t_atta_info where RELATION_TYPE ='23' GROUP BY DOMAIN_ID ) b on a.id=b.DOMAIN_ID
where b.DOMAIN_ID is not null
</select>
</mapper>
yifu-batch/yifu-batch-biz/src/main/resources/mapper/TElectronicArchiveDetailMapper.xml
0 → 100644
View file @
3ffe3bb0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yifu.cloud.plus.v1.batch.mapper.TElectronicArchiveDetailMapper"
>
<resultMap
id=
"tElectronicArchiveDetailMap"
type=
"com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail"
>
<id
property=
"id"
column=
"ID"
/>
<result
property=
"empName"
column=
"EMP_NAME"
/>
<result
property=
"empIdcard"
column=
"EMP_IDCARD"
/>
<result
property=
"deptNo"
column=
"DEPT_NO"
/>
<result
property=
"deptName"
column=
"DEPT_NAME"
/>
<result
property=
"customerName"
column=
"CUSTOMER_NAME"
/>
<result
property=
"customerCode"
column=
"CUSTOMER_CODE"
/>
<result
property=
"materialType"
column=
"MATERIAL_TYPE"
/>
<result
property=
"fileProvince"
column=
"FILE_PROVINCE"
/>
<result
property=
"fileCity"
column=
"FILE_CITY"
/>
<result
property=
"fileTown"
column=
"FILE_TOWN"
/>
<result
property=
"status"
column=
"STATUS"
/>
<result
property=
"deleteFlag"
column=
"DELETE_FLAG"
/>
<result
property=
"createBy"
column=
"CREATE_BY"
/>
<result
property=
"createName"
column=
"CREATE_NAME"
/>
<result
property=
"createTime"
column=
"CREATE_TIME"
/>
<result
property=
"updateBy"
column=
"UPDATE_BY"
/>
<result
property=
"updateTime"
column=
"UPDATE_TIME"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
a.ID,
a.EMP_NAME,
a.EMP_IDCARD,
a.DEPT_NO,
a.DEPT_NAME,
a.CUSTOMER_NAME,
a.CUSTOMER_CODE,
a.MATERIAL_TYPE,
a.FILE_PROVINCE,
a.FILE_CITY,
a.FILE_TOWN,
a.STATUS,
a.DELETE_FLAG,
a.CREATE_BY,
a.CREATE_NAME,
a.CREATE_TIME,
a.UPDATE_BY,
a.UPDATE_TIME
</sql>
<sql
id=
"tElectronicArchiveDetail_where"
>
<if
test=
"tElectronicArchiveDetail != null"
>
<if
test=
"tElectronicArchiveDetail.id != null and tElectronicArchiveDetail.id.trim() != ''"
>
AND a.ID = #{tElectronicArchiveDetail.id}
</if>
<if
test=
"tElectronicArchiveDetail.empName != null and tElectronicArchiveDetail.empName.trim() != ''"
>
AND a.EMP_NAME like concat('%', #{tElectronicArchiveDetail.empName}, '%')
</if>
<if
test=
"tElectronicArchiveDetail.empIdcard != null and tElectronicArchiveDetail.empIdcard.trim() != ''"
>
AND a.EMP_IDCARD = #{tElectronicArchiveDetail.empIdcard}
</if>
<if
test=
"tElectronicArchiveDetail.deptNo != null and tElectronicArchiveDetail.deptNo.trim() != ''"
>
AND a.DEPT_NO = #{tElectronicArchiveDetail.deptNo}
</if>
<if
test=
"tElectronicArchiveDetail.deptName != null and tElectronicArchiveDetail.deptName.trim() != ''"
>
AND a.DEPT_NAME like concat('%', #{tElectronicArchiveDetail.deptName}, '%')
</if>
<if
test=
"tElectronicArchiveDetail.customerName != null and tElectronicArchiveDetail.customerName.trim() != ''"
>
AND a.CUSTOMER_NAME like concat('%', #{tElectronicArchiveDetail.customerName}, '%')
</if>
<if
test=
"tElectronicArchiveDetail.customerCode != null and tElectronicArchiveDetail.customerCode.trim() != ''"
>
AND a.CUSTOMER_CODE = #{tElectronicArchiveDetail.customerCode}
</if>
<if
test=
"tElectronicArchiveDetail.typeList != null and tElectronicArchiveDetail.typeList.size() > 0"
>
AND a.MATERIAL_TYPE in
<foreach
item=
"item"
index=
"index"
collection=
"tElectronicArchiveDetail.typeList"
open=
"("
separator=
","
close=
")"
>
'${item}'
</foreach>
</if>
<if
test=
"tElectronicArchiveDetail.fileProvince != null"
>
AND a.FILE_PROVINCE = #{tElectronicArchiveDetail.fileProvince}
</if>
<if
test=
"tElectronicArchiveDetail.fileCity != null"
>
AND a.FILE_CITY = #{tElectronicArchiveDetail.fileCity}
</if>
<if
test=
"tElectronicArchiveDetail.fileTown != null"
>
AND a.FILE_TOWN = #{tElectronicArchiveDetail.fileTown}
</if>
<if
test=
"tElectronicArchiveDetail.status != null and tElectronicArchiveDetail.status.trim() != ''"
>
AND a.STATUS = #{tElectronicArchiveDetail.status}
</if>
<if
test=
"tElectronicArchiveDetail.createBy != null and tElectronicArchiveDetail.createBy.trim() != ''"
>
AND a.CREATE_BY = #{tElectronicArchiveDetail.createBy}
</if>
</if>
</sql>
<!--tElectronicArchiveDetail简单分页查询-->
<select
id=
"getTElectronicArchiveDetailPage"
resultMap=
"tElectronicArchiveDetailMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_electronic_archive_detail a
<where>
a.DELETE_FLAG = '0'
<include
refid=
"tElectronicArchiveDetail_where"
/>
</where>
</select>
</mapper>
yifu-batch/yifu-batch-biz/src/main/resources/mapper/TElectronicArchiveTaskMapper.xml
0 → 100644
View file @
3ffe3bb0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yifu.cloud.plus.v1.batch.mapper.TElectronicArchiveTaskMapper"
>
<resultMap
id=
"tElectronicArchiveTaskMap"
type=
"com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask"
>
<id
property=
"id"
column=
"ID"
/>
<result
property=
"taskCode"
column=
"TASK_CODE"
/>
<result
property=
"uploadFileName"
column=
"UPLOAD_FILE_NAME"
/>
<result
property=
"uploadZipName"
column=
"UPLOAD_ZIP_NAME"
/>
<result
property=
"status"
column=
"STATUS"
/>
<result
property=
"deleteFlag"
column=
"DELETE_FLAG"
/>
<result
property=
"createBy"
column=
"CREATE_BY"
/>
<result
property=
"createName"
column=
"CREATE_NAME"
/>
<result
property=
"createTime"
column=
"CREATE_TIME"
/>
<result
property=
"updateBy"
column=
"UPDATE_BY"
/>
<result
property=
"updateTime"
column=
"UPDATE_TIME"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
a.ID,
a.TASK_CODE,
a.UPLOAD_FILE_NAME,
a.UPLOAD_ZIP_NAME,
a.STATUS,
a.DELETE_FLAG,
a.CREATE_BY,
a.CREATE_NAME,
a.CREATE_TIME,
a.UPDATE_BY,
a.UPDATE_TIME
</sql>
<sql
id=
"tElectronicArchiveTask_where"
>
<if
test=
"tElectronicArchiveTask != null"
>
<if
test=
"tElectronicArchiveTask.id != null and tElectronicArchiveTask.id.trim() != ''"
>
AND a.ID = #{tElectronicArchiveTask.id}
</if>
<if
test=
"tElectronicArchiveTask.taskCode != null and tElectronicArchiveTask.taskCode.trim() != ''"
>
AND a.TASK_CODE = #{tElectronicArchiveTask.taskCode}
</if>
<if
test=
"tElectronicArchiveTask.typeList != null and tElectronicArchiveTask.typeList.size() > 0"
>
AND a.STATUS in
<foreach
item=
"item"
index=
"index"
collection=
"tElectronicArchiveTask.typeList"
open=
"("
separator=
","
close=
")"
>
'${item}'
</foreach>
</if>
<if
test=
"tElectronicArchiveTask.deleteFlag != null and tElectronicArchiveTask.deleteFlag.trim() != ''"
>
AND a.DELETE_FLAG = #{tElectronicArchiveTask.deleteFlag}
</if>
<if
test=
"tElectronicArchiveTask.createBy != null and tElectronicArchiveTask.createBy.trim() != ''"
>
AND a.CREATE_BY = #{tElectronicArchiveTask.createBy}
</if>
<if
test=
"tElectronicArchiveTask.createName != null and tElectronicArchiveTask.createName.trim() != ''"
>
AND a.CREATE_NAME like concat('%', #{tElectronicArchiveTask.createName}, '%')
</if>
<if
test=
"tElectronicArchiveTask.createTimeStart != null"
>
AND a.CREATE_TIME
<![CDATA[ >= ]]>
#{tElectronicArchiveTask.createTimeStart}
</if>
<if
test=
"tElectronicArchiveTask.createTimeEnd != null"
>
AND a.CREATE_TIME
<![CDATA[ <= ]]>
#{tElectronicArchiveTask.createTimeEnd}
</if>
</if>
</sql>
<!--tElectronicArchiveTask简单分页查询-->
<select
id=
"getTElectronicArchiveTaskPage"
resultMap=
"tElectronicArchiveTaskMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_electronic_archive_task a
<where>
a.DELETE_FLAG = '0'
<include
refid=
"tElectronicArchiveTask_where"
/>
</where>
</select>
</mapper>
yifu-batch/yifu-batch-biz/src/main/resources/mapper/TTaskArchiveRelationMapper.xml
0 → 100644
View file @
3ffe3bb0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yifu.cloud.plus.v1.batch.mapper.TTaskArchiveRelationMapper"
>
<resultMap
id=
"tTaskArchiveRelationMap"
type=
"com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation"
>
<id
property=
"id"
column=
"ID"
/>
<result
property=
"taskId"
column=
"TASK_ID"
/>
<result
property=
"archiveDetailId"
column=
"ARCHIVE_DETAIL_ID"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
a.ID,
a.TASK_ID,
a.ARCHIVE_DETAIL_ID
</sql>
<sql
id=
"tTaskArchiveRelation_where"
>
<if
test=
"tTaskArchiveRelation != null"
>
<if
test=
"tTaskArchiveRelation.id != null and tTaskArchiveRelation.id.trim() != ''"
>
AND a.ID = #{tTaskArchiveRelation.id}
</if>
<if
test=
"tTaskArchiveRelation.taskId != null and tTaskArchiveRelation.taskId.trim() != ''"
>
AND a.TASK_ID = #{tTaskArchiveRelation.taskId}
</if>
<if
test=
"tTaskArchiveRelation.archiveDetailId != null and tTaskArchiveRelation.archiveDetailId.trim() != ''"
>
AND a.ARCHIVE_DETAIL_ID = #{tTaskArchiveRelation.archiveDetailId}
</if>
</if>
</sql>
<!--tTaskArchiveRelation简单分页查询-->
<select
id=
"getTTaskArchiveRelationPage"
resultMap=
"tTaskArchiveRelationMap"
>
SELECT
<include
refid=
"Base_Column_List"
/>
FROM t_task_archive_relation a
<where>
1=1
<include
refid=
"tTaskArchiveRelation_where"
/>
</where>
</select>
</mapper>
yifu-common/yifu-common-core/src/main/java/com/yifu/cloud/plus/v1/yifu/common/core/constant/CacheConstants.java
View file @
3ffe3bb0
...
...
@@ -223,4 +223,11 @@ public interface CacheConstants {
* 项目下用户部门及权限缓存
*/
String
PROJECT_USER_PERMISSION
=
"mvp_project_user_permission:"
;
/**
* @Description: 每日电子档案任务编码缓存
* @Author: huych
* @Date: 2025/12/17
**/
String
ARCHIVE_TASK_CODE
=
"archive_task_code"
;
}
yifu-common/yifu-common-dapr/src/main/java/com/yifu/cloud/plus/v1/yifu/common/dapr/util/ArchivesDaprUtil.java
View file @
3ffe3bb0
...
...
@@ -14,7 +14,6 @@ import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchListVO
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchVO
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprArchivesProperties
;
import
com.yifu.cloud.plus.v1.yifu.insurances.vo.AutoDeptVO
;
import
com.yifu.cloud.plus.v1.yifu.salary.vo.TInsuranceUnpurchasePersonCardVo
;
...
...
@@ -262,6 +261,23 @@ public class ArchivesDaprUtil {
return
res
;
}
/**
* @param vo
* @Description: 获取档案基本信息
* @Author: huyc
* @Date: 2025/12/17 14:48
* @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeInfo>
**/
public
R
<
TEmployeeInfo
>
getTEmployeeInfoByIdcardAndName
(
IdNameNoVo
vo
)
{
R
<
TEmployeeInfo
>
res
=
HttpDaprUtil
.
invokeMethodPost
(
daprArchivesProperties
.
getAppUrl
(),
daprArchivesProperties
.
getAppId
()
,
"/temployeeinfo/inner/getTEmployeeInfoByIdcardAndName"
,
JSON
.
toJSONString
(
vo
),
TEmployeeInfo
.
class
,
SecurityConstants
.
FROM_IN
);
if
(
Common
.
isEmpty
(
res
)){
return
R
.
failed
(
"获取档案信息失败!"
);
}
return
res
;
}
/**
* @Description: 获取项目档案基本信息
* @Author: hgw
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment