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
95a0457f
Commit
95a0457f
authored
Jan 06, 2026
by
huyuchen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
huych-电子档案批量导入第
🈚
次提交
parent
6a8a1676
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
245 additions
and
20 deletions
+245
-20
ElectronicArchiveImportServiceImpl.java
...atch/service/impl/ElectronicArchiveImportServiceImpl.java
+245
-20
No files found.
yifu-batch/yifu-batch-biz/src/main/java/com/yifu/cloud/plus/v1/batch/service/impl/ElectronicArchiveImportServiceImpl.java
View file @
95a0457f
...
@@ -523,11 +523,6 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
...
@@ -523,11 +523,6 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
List
<
TElectronicArchiveDetail
>
details
=
detailService
.
listByIds
(
detailIds
);
List
<
TElectronicArchiveDetail
>
details
=
detailService
.
listByIds
(
detailIds
);
Map
<
String
,
TElectronicArchiveDetail
>
detailMap
=
details
.
stream
()
.
collect
(
Collectors
.
toMap
(
d
->
d
.
getEmpIdcard
()
+
"_"
+
d
.
getEmpName
(),
d
->
d
));
// 创建临时目录用于解压ZIP文件
// 创建临时目录用于解压ZIP文件
String
tempDirPath
=
System
.
getProperty
(
"java.io.tmpdir"
)
+
File
.
separator
+
"archive_file"
+
File
.
separator
String
tempDirPath
=
System
.
getProperty
(
"java.io.tmpdir"
)
+
File
.
separator
+
"archive_file"
+
File
.
separator
...
@@ -561,25 +556,102 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
...
@@ -561,25 +556,102 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
return
R
.
failed
(
"解压ZIP文件失败:"
+
e
.
getMessage
()
+
",请检查ZIP文件是否完整且格式正确"
);
return
R
.
failed
(
"解压ZIP文件失败:"
+
e
.
getMessage
()
+
",请检查ZIP文件是否完整且格式正确"
);
}
}
// 获取ZIP包的根目录(第一级目录,身份证+姓名目录)
// 获取ZIP包的根目录(第一级目录,身份证+姓名目录)
File
[]
zipRootDirs
=
tempDir
.
listFiles
(
File:
:
isDirectory
);
File
[]
zipRootDirs
=
tempDir
.
listFiles
(
File:
:
isDirectory
);
if
(
zipRootDirs
==
null
||
zipRootDirs
.
length
==
0
)
{
Map
<
String
,
File
>
zipDirMap
=
new
HashMap
<>();
updateTaskStatus
(
task
,
ArchiveConstants
.
TASK_STATUS_NOT_UPLOADED
);
if
(
zipRootDirs
!=
null
&&
zipRootDirs
.
length
>
0
)
{
return
R
.
failed
(
"ZIP文件格式不正确"
);
// 将ZIP中的目录按照 身份证_姓名 建立映射
for
(
File
personDir
:
zipRootDirs
)
{
String
dirName
=
personDir
.
getName
();
Map
<
String
,
String
>
idNameMap
=
parseIdCardAndName
(
dirName
);
if
(!
idNameMap
.
isEmpty
()
&&
idNameMap
.
containsKey
(
"idCard"
)
&&
idNameMap
.
containsKey
(
"name"
))
{
String
uniqueKey
=
idNameMap
.
get
(
"idCard"
)
+
"_"
+
idNameMap
.
get
(
"name"
);
zipDirMap
.
put
(
uniqueKey
,
personDir
);
}
}
}
}
// 遍历每个人员目录,递归处理所有附件
// 按照第一步Excel导入的明细列表生成反馈表
for
(
File
personDir
:
zipRootDirs
)
{
// 用于记录每个人员的处理结果(一个人可能有多个资料类型)
processPersonDirectory
(
personDir
,
detailMap
,
feedbackList
,
taskId
);
Map
<
String
,
List
<
String
>>
personMaterialTypesMap
=
new
HashMap
<>();
Map
<
String
,
String
>
personProcessResultMap
=
new
HashMap
<>();
Map
<
String
,
String
>
personFailReasonMap
=
new
HashMap
<>();
// 遍历第一步导入的所有明细
for
(
TElectronicArchiveDetail
detail
:
details
)
{
String
uniqueKey
=
detail
.
getEmpIdcard
()
+
"_"
+
detail
.
getEmpName
();
// 检查ZIP中是否存在该人员的目录
File
personDir
=
zipDirMap
.
get
(
uniqueKey
);
if
(
personDir
==
null
)
{
// ZIP中没有该人员的文件夹,记录为跳过
personProcessResultMap
.
put
(
uniqueKey
,
ArchiveConstants
.
PROCESS_RESULT_SKIP
);
personFailReasonMap
.
put
(
uniqueKey
,
"压缩包中未找到对应文件夹,跳过处理"
);
personMaterialTypesMap
.
put
(
uniqueKey
,
new
ArrayList
<>());
}
else
{
// ZIP中存在该人员的文件夹,处理其附件
List
<
String
>
materialTypes
=
new
ArrayList
<>();
List
<
String
>
failReasons
=
new
ArrayList
<>();
processPersonDirectoryWithResult
(
personDir
,
detail
,
materialTypes
,
failReasons
,
taskId
);
personMaterialTypesMap
.
put
(
uniqueKey
,
materialTypes
);
// 判断处理结果
if
(
materialTypes
.
isEmpty
())
{
// 没有成功上传任何资料类型,记录为失败
personProcessResultMap
.
put
(
uniqueKey
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
);
if
(
failReasons
.
isEmpty
())
{
personFailReasonMap
.
put
(
uniqueKey
,
"文件夹为空或格式不符"
);
}
else
{
personFailReasonMap
.
put
(
uniqueKey
,
String
.
join
(
";"
,
failReasons
));
}
}
else
{
// 有成功上传的资料类型
if
(
failReasons
.
isEmpty
())
{
personProcessResultMap
.
put
(
uniqueKey
,
ArchiveConstants
.
PROCESS_RESULT_SUCCESS
);
personFailReasonMap
.
put
(
uniqueKey
,
""
);
}
else
{
// 部分成功,部分失败
personProcessResultMap
.
put
(
uniqueKey
,
ArchiveConstants
.
PROCESS_RESULT_FAILED
);
personFailReasonMap
.
put
(
uniqueKey
,
String
.
join
(
";"
,
failReasons
));
}
}
}
}
}
// 处理完成,更新任务状态
// 按照第一步Excel的顺序生成反馈表
task
.
setStatus
(
ArchiveConstants
.
TASK_STATUS_GENERATED
);
for
(
TElectronicArchiveDetail
detail
:
details
)
{
taskService
.
updateById
(
task
);
String
uniqueKey
=
detail
.
getEmpIdcard
()
+
"_"
+
detail
.
getEmpName
();
ArchiveFeedbackVO
feedback
=
new
ArchiveFeedbackVO
();
feedback
.
setEmpName
(
detail
.
getEmpName
());
feedback
.
setEmpIdcard
(
detail
.
getEmpIdcard
());
feedback
.
setDeptNo
(
detail
.
getDeptNo
());
feedback
.
setDeptName
(
detail
.
getDeptName
());
// 设置资料类型(多个用逗号拼接)
List
<
String
>
materialTypes
=
personMaterialTypesMap
.
get
(
uniqueKey
);
if
(
materialTypes
!=
null
&&
!
materialTypes
.
isEmpty
())
{
feedback
.
setMaterialType
(
String
.
join
(
","
,
materialTypes
));
}
else
{
feedback
.
setMaterialType
(
""
);
}
feedback
.
setProcessResult
(
personProcessResultMap
.
get
(
uniqueKey
));
feedback
.
setFailReason
(
personFailReasonMap
.
get
(
uniqueKey
));
feedbackList
.
add
(
feedback
);
}
// 处理完成,更新任务状态
task
.
setStatus
(
ArchiveConstants
.
TASK_STATUS_GENERATED
);
taskService
.
updateById
(
task
);
// 生成反馈表
// 生成反馈表
generateFeedbackExcel
(
task
,
feedbackList
);
generateFeedbackExcel
(
task
,
feedbackList
);
return
R
.
ok
(
"处理完成"
);
return
R
.
ok
(
"处理完成"
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"异步处理任务失败,任务ID:{}"
,
taskId
,
e
);
log
.
error
(
"异步处理任务失败,任务ID:{}"
,
taskId
,
e
);
...
@@ -656,7 +728,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
...
@@ -656,7 +728,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
}
}
/**
/**
* 处理单个人员目录
* 处理单个人员目录
(旧方法,保留向后兼容)
*/
*/
private
void
processPersonDirectory
(
File
personDir
,
Map
<
String
,
TElectronicArchiveDetail
>
detailMap
,
private
void
processPersonDirectory
(
File
personDir
,
Map
<
String
,
TElectronicArchiveDetail
>
detailMap
,
List
<
ArchiveFeedbackVO
>
feedbackList
,
String
taskId
)
{
List
<
ArchiveFeedbackVO
>
feedbackList
,
String
taskId
)
{
...
@@ -742,6 +814,76 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
...
@@ -742,6 +814,76 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
}
}
}
}
/**
* 处理单个人员目录(返回处理结果,用于按Excel顺序生成反馈表)
*
* @param personDir 人员目录
* @param detail 电子档案明细
* @param materialTypes 成功处理的资料类型列表(输出参数)
* @param failReasons 失败原因列表(输出参数)
* @param taskId 任务ID
*/
private
void
processPersonDirectoryWithResult
(
File
personDir
,
TElectronicArchiveDetail
detail
,
List
<
String
>
materialTypes
,
List
<
String
>
failReasons
,
String
taskId
)
{
// 处理第三级目录(资料类型或直接是文件)
File
[]
subFiles
=
personDir
.
listFiles
();
if
(
subFiles
==
null
||
subFiles
.
length
==
0
)
{
// 文件夹为空
failReasons
.
add
(
"文件夹为空"
);
return
;
}
// 用于记录该人员的所有资料类型
Set
<
String
>
materialTypesSet
=
new
HashSet
<>();
// 遍历第三级,按资料类型分组处理所有文件
for
(
File
subFile
:
subFiles
)
{
if
(
subFile
.
isDirectory
())
{
// 是资料类型目录
String
materialType
=
subFile
.
getName
();
//存量、新签、续签、减员
if
(
materialType
.
contains
(
"存量"
))
{
materialType
=
"存量"
;
}
else
if
(
materialType
.
contains
(
"新签"
))
{
materialType
=
"新签"
;
}
else
if
(
materialType
.
contains
(
"续签"
))
{
materialType
=
"续签"
;
}
else
if
(
materialType
.
contains
(
"减员"
))
{
materialType
=
"减员"
;
}
if
(
isValidMaterialType
(
materialType
))
{
// 不是有效的资料类型,跳过
continue
;
}
// 按资料类型分组处理目录下的所有文件
String
result
=
processMaterialTypeDirectoryWithResult
(
subFile
,
detail
,
materialType
,
taskId
);
if
(
"success"
.
equals
(
result
))
{
materialTypesSet
.
add
(
materialType
);
}
else
{
failReasons
.
add
(
materialType
+
":"
+
result
);
}
}
else
{
// 直接是文件,默认为存量类型,按单个文件处理
List
<
File
>
singleFileList
=
new
ArrayList
<>();
singleFileList
.
add
(
subFile
);
String
result
=
processMaterialTypeFilesWithResult
(
singleFileList
,
detail
,
ArchiveConstants
.
MATERIAL_TYPE_STOCK
,
taskId
);
if
(
"success"
.
equals
(
result
))
{
materialTypesSet
.
add
(
ArchiveConstants
.
MATERIAL_TYPE_STOCK
);
}
else
{
failReasons
.
add
(
ArchiveConstants
.
MATERIAL_TYPE_STOCK
+
":"
+
result
);
}
}
}
// 更新明细表的资料类型和状态
if
(!
materialTypesSet
.
isEmpty
())
{
materialTypes
.
addAll
(
materialTypesSet
);
updateDetailMaterialType
(
detail
,
materialTypesSet
);
}
}
/**
/**
* 按资料类型处理目录下的所有文件
* 按资料类型处理目录下的所有文件
* 同一资料类型下的所有文件作为一个整体处理:先验证所有文件,全部通过后才统一上传
* 同一资料类型下的所有文件作为一个整体处理:先验证所有文件,全部通过后才统一上传
...
@@ -764,6 +906,29 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
...
@@ -764,6 +906,29 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 统一处理该资料类型下的所有文件
// 统一处理该资料类型下的所有文件
processMaterialTypeFiles
(
allFiles
,
detail
,
materialType
,
feedbackList
,
materialTypes
,
taskId
);
processMaterialTypeFiles
(
allFiles
,
detail
,
materialType
,
feedbackList
,
materialTypes
,
taskId
);
}
}
/**
* 按资料类型处理目录下的所有文件(返回处理结果)
*
* @param directory 资料类型目录
* @param detail 电子档案明细
* @param materialType 资料类型
* @param taskId 任务ID
* @return "success" 表示成功,其他表示失败原因
*/
private
String
processMaterialTypeDirectoryWithResult
(
File
directory
,
TElectronicArchiveDetail
detail
,
String
materialType
,
String
taskId
)
{
// 收集该资料类型目录下的所有文件(递归收集子目录中的文件)
List
<
File
>
allFiles
=
new
ArrayList
<>();
collectAllFiles
(
directory
,
allFiles
);
if
(
allFiles
.
isEmpty
())
{
return
"文件夹为空"
;
}
// 统一处理该资料类型下的所有文件
return
processMaterialTypeFilesWithResult
(
allFiles
,
detail
,
materialType
,
taskId
);
}
/**
/**
* 递归收集目录下的所有文件
* 递归收集目录下的所有文件
...
@@ -858,6 +1023,66 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
...
@@ -858,6 +1023,66 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
}
}
}
}
/**
* 统一处理同一资料类型下的所有文件(返回处理结果)
*
* @param files 文件列表
* @param detail 电子档案明细
* @param materialType 资料类型
* @param taskId 任务ID
* @return "success" 表示成功,其他表示失败原因
*/
private
String
processMaterialTypeFilesWithResult
(
List
<
File
>
files
,
TElectronicArchiveDetail
detail
,
String
materialType
,
String
taskId
)
{
// 第一步:验证所有文件格式
for
(
File
file
:
files
)
{
String
fileName
=
file
.
getName
();
if
(
checkFileFormat
(
fileName
))
{
// 有文件格式不符,整体失败
return
"文件格式不符,文件格式需为png\\jpg\\jpeg\\xlsx\\xls\\doc\\docx\\pdf\\ppt\\pptx\\txt:"
+
fileName
;
}
}
// 第二步:所有文件格式验证通过,统一上传到阿里云
try
{
// 构建OSS目录路径
String
ossDirectory
=
buildOssDirectory
(
detail
,
materialType
);
// 依次上传每个文件
for
(
File
file
:
files
)
{
String
fileName
=
file
.
getName
();
// 转换为MultipartFile
MultipartFile
multipartFile
=
fileToMultipartFile
(
file
);
if
(
multipartFile
==
null
)
{
// 文件转换失败,整体失败
return
"文件转换失败:"
+
fileName
;
}
// 上传文件到阿里云OSS,uploadFileReturnAtta会自动生成TAttaInfo记录
R
<
TAttaInfo
>
uploadResult
=
fileUploadService
.
uploadFileReturnAtta
(
multipartFile
,
ossDirectory
,
CommonConstants
.
FOUR_STRING
,
detail
.
getId
(),
taskId
);
if
(!
R
.
isSuccess
(
uploadResult
))
{
// 上传失败,整体失败
return
"文件上传失败:"
+
fileName
+
",原因:"
+
(
uploadResult
!=
null
?
uploadResult
.
getMsg
()
:
"未知错误"
);
}
}
// 第三步:所有文件上传成功
return
"success"
;
}
catch
(
Exception
e
)
{
log
.
error
(
"上传文件失败,资料类型:{},电子档案详情ID:{},任务ID:{}"
,
materialType
,
detail
.
getId
(),
taskId
,
e
);
return
"文件上传异常,原因:"
+
e
.
getMessage
();
}
}
/**
/**
* 构建OSS目录路径
* 构建OSS目录路径
...
...
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