Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
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
54918760
Commit
54918760
authored
Jun 16, 2026
by
hongguangwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1.7.24 - 派单审核时,抓取身份证、合同信息
parent
66b875b5
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
704 additions
and
3 deletions
+704
-3
IdCardAttaVo.java
...com/yifu/cloud/plus/v1/yifu/archives/vo/IdCardAttaVo.java
+1
-0
IdCardQueryVo.java
...om/yifu/cloud/plus/v1/yifu/archives/vo/IdCardQueryVo.java
+1
-0
TEmployeeContractInfoController.java
.../archives/controller/TEmployeeContractInfoController.java
+9
-0
TEmployeeInfoController.java
.../v1/yifu/archives/controller/TEmployeeInfoController.java
+9
-0
TEmployeeContractInfoMapper.java
.../v1/yifu/archives/mapper/TEmployeeContractInfoMapper.java
+2
-0
TEmployeeContractInfoService.java
...1/yifu/archives/service/TEmployeeContractInfoService.java
+5
-0
TEmployeeInfoService.java
...d/plus/v1/yifu/archives/service/TEmployeeInfoService.java
+5
-0
TEmployeeContractInfoServiceImpl.java
...chives/service/impl/TEmployeeContractInfoServiceImpl.java
+25
-0
TEmployeeInfoServiceImpl.java
.../yifu/archives/service/impl/TEmployeeInfoServiceImpl.java
+35
-0
TEmployeeContractInfoMapper.xml
...src/main/resources/mapper/TEmployeeContractInfoMapper.xml
+11
-0
ArchivesDaprUtil.java
...cloud/plus/v1/yifu/common/dapr/util/ArchivesDaprUtil.java
+33
-0
DispatchConstants.java
...loud/plus/v1/yifu/social/constants/DispatchConstants.java
+21
-0
TAttaInfo.java
.../com/yifu/cloud/plus/v1/yifu/social/entity/TAttaInfo.java
+2
-1
pom.xml
yifu-social/yifu-social-biz/pom.xml
+5
-0
FileUploadController.java
.../plus/v1/yifu/social/controller/FileUploadController.java
+1
-0
TDispatchInfoController.java
...us/v1/yifu/social/controller/TDispatchInfoController.java
+16
-0
DispatchIdCardService.java
...ud/plus/v1/yifu/social/service/DispatchIdCardService.java
+18
-0
DispatchIdCardServiceImpl.java
...1/yifu/social/service/impl/DispatchIdCardServiceImpl.java
+226
-0
TSocialFriendPushServiceImpl.java
...ifu/social/service/impl/TSocialFriendPushServiceImpl.java
+6
-2
ContractPdfUtil.java
.../yifu/cloud/plus/v1/yifu/social/util/ContractPdfUtil.java
+51
-0
IdCardMergeUtil.java
.../yifu/cloud/plus/v1/yifu/social/util/IdCardMergeUtil.java
+222
-0
No files found.
yifu-archives/yifu-archives-api/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/vo/IdCardAttaVo.java
0 → 100644
View file @
54918760
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
archives
.
vo
;
import
lombok.Data
;
import
java.io.Serializable
;
/** * 人员档案身份证正反面附件信息 */
@Data
public
class
IdCardAttaVo
implements
Serializable
{
// 员工id private String empId; // 员工身份证正面图片 private String frontAttaSrc; private String frontAttaName; // 员工身份证反面图片 private String backAttaSrc; private String backAttaName; // 员工合同pdf private String contractAttaSrc; private String contractAttaName; }
\ No newline at end of file
yifu-archives/yifu-archives-api/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/vo/IdCardQueryVo.java
0 → 100644
View file @
54918760
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
archives
.
vo
;
import
lombok.Data
;
import
java.io.Serializable
;
/** * 查询人员档案身份证附件入参 */
@Data
public
class
IdCardQueryVo
implements
Serializable
{
private
String
empId
;
private
String
empIdcard
;
private
String
deptNo
;
}
\ No newline at end of file
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/controller/TEmployeeContractInfoController.java
View file @
54918760
...
@@ -455,4 +455,13 @@ public class TEmployeeContractInfoController {
...
@@ -455,4 +455,13 @@ public class TEmployeeContractInfoController {
return
tEmployeeContractInfoService
.
selectExitEmpCopntractNew
(
cardVo
);
return
tEmployeeContractInfoService
.
selectExitEmpCopntractNew
(
cardVo
);
}
}
/**
* 内部接口:获取合同pdf OSS 信息
*/
@Inner
@PostMapping
(
"/inner/getContractAttaByEmpIdCard"
)
public
IdCardAttaVo
getIdCardAttaByEmpIdCard
(
@RequestBody
IdCardQueryVo
queryVo
)
{
return
tEmployeeContractInfoService
.
getContractAttaByEmpIdCard
(
queryVo
);
}
}
}
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/controller/TEmployeeInfoController.java
View file @
54918760
...
@@ -187,6 +187,15 @@ public class TEmployeeInfoController {
...
@@ -187,6 +187,15 @@ public class TEmployeeInfoController {
return
tEmployeeInfoService
.
getInfoByIdcard
(
idcard
);
return
tEmployeeInfoService
.
getInfoByIdcard
(
idcard
);
}
}
/**
* 内部接口:获取人员档案身份证正反面 OSS 信息
*/
@Inner
@PostMapping
(
"/inner/getIdCardAttaByEmpIdCard"
)
public
IdCardAttaVo
getIdCardAttaByEmpIdCard
(
@RequestBody
IdCardQueryVo
queryVo
)
{
return
tEmployeeInfoService
.
getIdCardAttaByEmpIdCard
(
queryVo
);
}
/**
/**
* @param empName 姓名
* @param empName 姓名
* @param empIdCard 身份证
* @param empIdCard 身份证
...
...
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/mapper/TEmployeeContractInfoMapper.java
View file @
54918760
...
@@ -115,6 +115,8 @@ public interface TEmployeeContractInfoMapper extends BaseMapper<TEmployeeContrac
...
@@ -115,6 +115,8 @@ public interface TEmployeeContractInfoMapper extends BaseMapper<TEmployeeContrac
String
getContractByEmpIdCardAndDeptId
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptId"
)
String
deptId
);
String
getContractByEmpIdCardAndDeptId
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptId"
)
String
deptId
);
String
getContractByEmpIdCardAndDeptNo
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptNo"
)
String
deptNo
);
String
getContractByEmpIdCardAndDeptNo
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptNo"
)
String
deptNo
);
/* 查询合同id,用来获取附件-派单审核用的 */
String
getContractForFile
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptNo"
)
String
deptNo
);
String
getContractByEmpIdCardAndDeptNoByEnd
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptNo"
)
String
deptNo
);
String
getContractByEmpIdCardAndDeptNoByEnd
(
@Param
(
"empIdCard"
)
String
empIdCard
,
@Param
(
"deptNo"
)
String
deptNo
);
String
getMinDateByCardAndDeptId
(
@Param
(
"vo"
)
IdNameNoVo
vo
);
String
getMinDateByCardAndDeptId
(
@Param
(
"vo"
)
IdNameNoVo
vo
);
...
...
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/service/TEmployeeContractInfoService.java
View file @
54918760
...
@@ -209,4 +209,9 @@ public interface TEmployeeContractInfoService extends IService<TEmployeeContract
...
@@ -209,4 +209,9 @@ public interface TEmployeeContractInfoService extends IService<TEmployeeContract
// 查找最近的终止合同
// 查找最近的终止合同
String
getContractByEmpIdCardAndDeptNoByEnd
(
String
empIdCard
,
String
deptNo
);
String
getContractByEmpIdCardAndDeptNoByEnd
(
String
empIdCard
,
String
deptNo
);
/**
* 获取合同pdf OSS 信息
*/
IdCardAttaVo
getContractAttaByEmpIdCard
(
IdCardQueryVo
queryVo
);
}
}
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/service/TEmployeeInfoService.java
View file @
54918760
...
@@ -306,4 +306,9 @@ public interface TEmployeeInfoService extends IService<TEmployeeInfo> {
...
@@ -306,4 +306,9 @@ public interface TEmployeeInfoService extends IService<TEmployeeInfo> {
BaseSearchVO
getEmpAndContractStatus
(
BaseSearchVO
paramVo
);
BaseSearchVO
getEmpAndContractStatus
(
BaseSearchVO
paramVo
);
/**
* 获取人员档案身份证正反面附件 OSS 信息
*/
IdCardAttaVo
getIdCardAttaByEmpIdCard
(
IdCardQueryVo
queryVo
);
}
}
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/service/impl/TEmployeeContractInfoServiceImpl.java
View file @
54918760
...
@@ -2793,4 +2793,29 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
...
@@ -2793,4 +2793,29 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
null
,
null
);
null
,
null
);
}
}
@Override
public
IdCardAttaVo
getContractAttaByEmpIdCard
(
IdCardQueryVo
queryVo
)
{
IdCardAttaVo
vo
=
new
IdCardAttaVo
();
if
(
queryVo
==
null
)
{
return
vo
;
}
String
doMainId
=
null
;
if
(
Common
.
isNotNull
(
queryVo
.
getEmpIdcard
()))
{
doMainId
=
baseMapper
.
getContractForFile
(
queryVo
.
getEmpIdcard
(),
queryVo
.
getDeptNo
());
}
if
(
Common
.
isEmpty
(
doMainId
))
{
return
vo
;
}
TAttaInfo
attaInfo
=
tAttaInfoService
.
getOne
(
Wrappers
.<
TAttaInfo
>
query
().
lambda
()
.
eq
(
TAttaInfo:
:
getDomainId
,
doMainId
)
.
eq
(
TAttaInfo:
:
getRelationType
,
CommonConstants
.
FOUR_STRING
)
.
orderByDesc
(
TAttaInfo:
:
getCreateTime
)
.
last
(
CommonConstants
.
LAST_ONE_SQL
));
if
(
Common
.
isNotNull
(
attaInfo
)
&&
Common
.
isNotNull
(
attaInfo
.
getAttaSrc
()))
{
vo
.
setContractAttaSrc
(
attaInfo
.
getAttaSrc
());
vo
.
setContractAttaName
(
attaInfo
.
getAttaName
());
}
return
vo
;
}
}
}
yifu-archives/yifu-archives-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/archives/service/impl/TEmployeeInfoServiceImpl.java
View file @
54918760
...
@@ -2859,6 +2859,41 @@ public class TEmployeeInfoServiceImpl extends ServiceImpl<TEmployeeInfoMapper, T
...
@@ -2859,6 +2859,41 @@ public class TEmployeeInfoServiceImpl extends ServiceImpl<TEmployeeInfoMapper, T
.
last
(
CommonConstants
.
LAST_ONE_SQL
));
.
last
(
CommonConstants
.
LAST_ONE_SQL
));
}
}
@Override
public
IdCardAttaVo
getIdCardAttaByEmpIdCard
(
IdCardQueryVo
queryVo
)
{
IdCardAttaVo
vo
=
new
IdCardAttaVo
();
if
(
queryVo
==
null
)
{
return
vo
;
}
String
empId
=
null
;
if
(
Common
.
isNotNull
(
queryVo
.
getEmpIdcard
()))
{
TEmployeeInfo
emp
=
getInfoByIdcard
(
queryVo
.
getEmpIdcard
());
if
(
emp
!=
null
)
{
empId
=
emp
.
getId
();
}
}
if
(
Common
.
isEmpty
(
empId
))
{
return
vo
;
}
vo
.
setEmpId
(
empId
);
List
<
TAttaInfo
>
attaList
=
attaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
query
().
lambda
()
.
eq
(
TAttaInfo:
:
getDomainId
,
empId
)
.
in
(
TAttaInfo:
:
getRelationType
,
"9"
,
"24"
)
.
orderByDesc
(
TAttaInfo:
:
getCreateTime
));
if
(
Common
.
isNotNull
(
attaList
))
{
for
(
TAttaInfo
atta
:
attaList
)
{
if
(
"9"
.
equals
(
atta
.
getRelationType
())
&&
Common
.
isEmpty
(
vo
.
getFrontAttaSrc
()))
{
vo
.
setFrontAttaSrc
(
atta
.
getAttaSrc
());
vo
.
setFrontAttaName
(
atta
.
getAttaName
());
}
else
if
(
"24"
.
equals
(
atta
.
getRelationType
())
&&
Common
.
isEmpty
(
vo
.
getBackAttaSrc
()))
{
vo
.
setBackAttaSrc
(
atta
.
getAttaSrc
());
vo
.
setBackAttaName
(
atta
.
getAttaName
());
}
}
}
return
vo
;
}
@Override
@Override
public
TEmployeeInfo
getTEmployeeInfoByIdcardAndName
(
IdNameNoVo
vo
)
{
public
TEmployeeInfo
getTEmployeeInfoByIdcardAndName
(
IdNameNoVo
vo
)
{
return
baseMapper
.
selectOne
(
Wrappers
.<
TEmployeeInfo
>
query
().
lambda
()
return
baseMapper
.
selectOne
(
Wrappers
.<
TEmployeeInfo
>
query
().
lambda
()
...
...
yifu-archives/yifu-archives-biz/src/main/resources/mapper/TEmployeeContractInfoMapper.xml
View file @
54918760
...
@@ -940,4 +940,15 @@
...
@@ -940,4 +940,15 @@
</where>
</where>
</select>
</select>
<!-- 查询合同id,用来获取附件 -->
<select
id=
"getContractForFile"
resultType=
"java.lang.String"
>
select
e.id
from t_employee_contract_info e
where e.EMP_IDCARD = #{empIdCard} and e.DEPT_NO = #{deptNo}
and e.DELETE_FLAG = '0'
AND e.IN_USE = '0' and e.TYPE='5' and e.IS_FILE = '0'
limit 1
</select>
</mapper>
</mapper>
yifu-common/yifu-common-dapr/src/main/java/com/yifu/cloud/plus/v1/yifu/common/dapr/util/ArchivesDaprUtil.java
View file @
54918760
...
@@ -262,6 +262,39 @@ public class ArchivesDaprUtil {
...
@@ -262,6 +262,39 @@ public class ArchivesDaprUtil {
return
res
;
return
res
;
}
}
/**
* 获取人员档案身份证正反面 OSS 信息
*/
public
R
<
IdCardAttaVo
>
getIdCardAttaByEmpIdCard
(
String
empIdcard
)
{
IdCardQueryVo
queryVo
=
new
IdCardQueryVo
();
queryVo
.
setEmpIdcard
(
empIdcard
);
R
<
IdCardAttaVo
>
res
=
HttpDaprUtil
.
invokeMethodPost
(
daprArchivesProperties
.
getAppUrl
(),
daprArchivesProperties
.
getAppId
(),
"/temployeeinfo/inner/getIdCardAttaByEmpIdCard"
,
JSON
.
toJSONString
(
queryVo
),
IdCardAttaVo
.
class
,
SecurityConstants
.
FROM_IN
);
if
(
Common
.
isEmpty
(
res
))
{
return
R
.
failed
(
"获取档案身份证信息失败!"
);
}
return
res
;
}
/**
* 获取人员合同 OSS 信息
*/
public
R
<
IdCardAttaVo
>
getContractAttaByEmpIdCard
(
String
empIdcard
,
String
deptNo
)
{
IdCardQueryVo
queryVo
=
new
IdCardQueryVo
();
queryVo
.
setEmpIdcard
(
empIdcard
);
queryVo
.
setDeptNo
(
deptNo
);
R
<
IdCardAttaVo
>
res
=
HttpDaprUtil
.
invokeMethodPost
(
daprArchivesProperties
.
getAppUrl
(),
daprArchivesProperties
.
getAppId
(),
"/temployeecontractinfo/inner/getContractAttaByEmpIdCard"
,
JSON
.
toJSONString
(
queryVo
),
IdCardAttaVo
.
class
,
SecurityConstants
.
FROM_IN
);
if
(
Common
.
isEmpty
(
res
))
{
return
R
.
failed
(
"获取合同附件信息失败!"
);
}
return
res
;
}
/**
/**
* @param vo
* @param vo
* @Description: 获取档案基本信息
* @Description: 获取档案基本信息
...
...
yifu-social/yifu-social-api/src/main/java/com/yifu/cloud/plus/v1/yifu/social/constants/DispatchConstants.java
View file @
54918760
...
@@ -204,7 +204,28 @@ public class DispatchConstants {
...
@@ -204,7 +204,28 @@ public class DispatchConstants {
public
static
final
String
EMPLOYEE
=
"员工:"
;
public
static
final
String
EMPLOYEE
=
"员工:"
;
/** 社保-档案身份证合成图 */
public
static
final
String
ATTA_TYPE_ID_CARD_MERGE_YGS
=
"15"
;
/** 医保-档案身份证合成图 */
public
static
final
String
ATTA_TYPE_ID_CARD_MERGE_YSD
=
"16"
;
/** 社保-档案合同合成图(预留) */
public
static
final
String
ATTA_TYPE_CONTRACT_MERGE_YGS
=
"17"
;
/** 医保-档案合同合成图(预留) */
public
static
final
String
ATTA_TYPE_CONTRACT_MERGE_YSD
=
"18"
;
public
static
final
String
MSG_NO_ID_CARD
=
"档案无身份证信息"
;
// 审核类型:自动化派单-无需审核
// 归档状态:已归档
// 合同状态:可用。
// 身份证+ 项目编码。
// 获取pdf类型的合同,转化为图片,压缩4M以下。
public
static
final
String
MSG_NO_CONTRACT
=
"档案无合同附件"
;
public
static
final
String
MSG_MERGE_FAILED
=
"合成失败"
;
}
}
yifu-social/yifu-social-api/src/main/java/com/yifu/cloud/plus/v1/yifu/social/entity/TAttaInfo.java
View file @
54918760
...
@@ -59,10 +59,11 @@ public class TAttaInfo extends BaseEntity {
...
@@ -59,10 +59,11 @@ public class TAttaInfo extends BaseEntity {
/**
/**
* 1户配置的章;2:派单审核附件,税友单个使用,社保3医保附件;11社保增花名册模板;12社保减花名册模板;13医保增花名册模板;14医保减花名册模板
* 1户配置的章;2:派单审核附件,税友单个使用,社保3医保附件;11社保增花名册模板;12社保减花名册模板;13医保增花名册模板;14医保减花名册模板
* 4:单个附件_社保_花名册;5:单个附件_医保_花名册;6:单个附件_解除劳动合同证明书(1.7.22版本)
* 4:单个附件_社保_花名册;5:单个附件_医保_花名册;6:单个附件_解除劳动合同证明书(1.7.22版本)
* 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图
*/
*/
@NotBlank
(
message
=
"关系类型不能为空"
)
@NotBlank
(
message
=
"关系类型不能为空"
)
@Length
(
max
=
2
,
message
=
"关系类型不能超过2个字符"
)
@Length
(
max
=
2
,
message
=
"关系类型不能超过2个字符"
)
@Schema
(
description
=
"关系类型(1户配置的章;2:派单审核附件,税友单个使用,社保;3医保附件;4:单个附件_社保_花名册;5:单个附件_医保_花名册;6:单个附件_解除劳动合同证明书;11社保增花名册模板;12社保减花名册模板;13医保增花名册模板;14医保减花名册模板)"
)
@Schema
(
description
=
"关系类型(1户配置的章;2:派单审核附件,税友单个使用,社保;3医保附件;4:单个附件_社保_花名册;5:单个附件_医保_花名册;6:单个附件_解除劳动合同证明书;1
5:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图;1
1社保增花名册模板;12社保减花名册模板;13医保增花名册模板;14医保减花名册模板)"
)
private
String
relationType
;
private
String
relationType
;
/**
/**
* 实体id和关系类型共同确定附件所属(9、10、21、22、23、24、25存项目档案id,0、2、26存附属表id)
* 实体id和关系类型共同确定附件所属(9、10、21、22、23、24、25存项目档案id,0、2、26存附属表id)
...
...
yifu-social/yifu-social-biz/pom.xml
View file @
54918760
...
@@ -122,6 +122,11 @@
...
@@ -122,6 +122,11 @@
<artifactId>
aspose-cells
</artifactId>
<artifactId>
aspose-cells
</artifactId>
<version>
23.1
</version>
<version>
23.1
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.apache.pdfbox
</groupId>
<artifactId>
pdfbox
</artifactId>
<version>
2.0.29
</version>
</dependency>
</dependencies>
</dependencies>
...
...
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/controller/FileUploadController.java
View file @
54918760
...
@@ -171,6 +171,7 @@ public class FileUploadController {
...
@@ -171,6 +171,7 @@ public class FileUploadController {
* @param domainId 关联id
* @param domainId 关联id
* @param type 类型 1户配置的章;2:派单审核附件,税友单个使用,社保3医保附件;11社保增花名册模板;12社保减花名册模板;13医保增花名册模板;14医保减花名册模板
* @param type 类型 1户配置的章;2:派单审核附件,税友单个使用,社保3医保附件;11社保增花名册模板;12社保减花名册模板;13医保增花名册模板;14医保减花名册模板
* 4:单个附件_社保_花名册;5:单个附件_医保_花名册;6:单个附件_解除劳动合同证明书(1.7.22版本)
* 4:单个附件_社保_花名册;5:单个附件_医保_花名册;6:单个附件_解除劳动合同证明书(1.7.22版本)
* 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图
* @Description: 获取社保服务的附件信息
* @Description: 获取社保服务的附件信息
* @Author: hgw
* @Author: hgw
* @Date: 2025/4/28 14:12
* @Date: 2025/4/28 14:12
...
...
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/controller/TDispatchInfoController.java
View file @
54918760
...
@@ -38,6 +38,8 @@ import com.yifu.cloud.plus.v1.yifu.common.log.annotation.SysLog;
...
@@ -38,6 +38,8 @@ import com.yifu.cloud.plus.v1.yifu.common.log.annotation.SysLog;
import
com.yifu.cloud.plus.v1.yifu.common.security.annotation.Inner
;
import
com.yifu.cloud.plus.v1.yifu.common.security.annotation.Inner
;
import
com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils
;
import
com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils
;
import
com.yifu.cloud.plus.v1.yifu.social.entity.TDispatchInfo
;
import
com.yifu.cloud.plus.v1.yifu.social.entity.TDispatchInfo
;
import
com.yifu.cloud.plus.v1.yifu.social.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.yifu.social.service.DispatchIdCardService
;
import
com.yifu.cloud.plus.v1.yifu.social.service.TDispatchInfoService
;
import
com.yifu.cloud.plus.v1.yifu.social.service.TDispatchInfoService
;
import
com.yifu.cloud.plus.v1.yifu.social.util.DoSocialTask
;
import
com.yifu.cloud.plus.v1.yifu.social.util.DoSocialTask
;
import
com.yifu.cloud.plus.v1.yifu.social.vo.*
;
import
com.yifu.cloud.plus.v1.yifu.social.vo.*
;
...
@@ -72,6 +74,8 @@ public class TDispatchInfoController {
...
@@ -72,6 +74,8 @@ public class TDispatchInfoController {
private
final
TDispatchInfoService
tDispatchInfoService
;
private
final
TDispatchInfoService
tDispatchInfoService
;
private
final
DispatchIdCardService
dispatchIdCardService
;
private
final
MenuUtil
menuUtil
;
private
final
MenuUtil
menuUtil
;
private
final
DaprArchivesProperties
daprArchivesProperties
;
private
final
DaprArchivesProperties
daprArchivesProperties
;
...
@@ -551,6 +555,18 @@ public class TDispatchInfoController {
...
@@ -551,6 +555,18 @@ public class TDispatchInfoController {
return
tDispatchInfoService
.
leaveToReduceSocialAndFund
(
paramVo
);
return
tDispatchInfoService
.
leaveToReduceSocialAndFund
(
paramVo
);
}
}
/**
* 派单审核前:从档案抓取身份证正反面,合成 PNG 并上传至派单附件
* relationType 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图
*/
@Operation
(
description
=
"派单审核前抓取档案身份证、合同归档附件合成上传,relationType 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图"
)
@SysLog
(
"派单抓取档案身份证、合同归档附件合成上传"
)
@GetMapping
(
"/generateIdCardImage"
)
public
R
<
TAttaInfo
>
generateIdCardImage
(
@RequestParam
String
dispatchId
,
@RequestParam
String
relationType
)
{
return
dispatchIdCardService
.
generateIdCardImage
(
dispatchId
,
relationType
);
}
/**
/**
* @Author fxj
* @Author fxj
* @Description 派单申请批量审核
* @Description 派单申请批量审核
...
...
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/service/DispatchIdCardService.java
0 → 100644
View file @
54918760
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
social
.
service
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.social.entity.TAttaInfo
;
/**
* 派单身份证合成附件服务
*/
public
interface
DispatchIdCardService
{
/**
* 从档案抓取身份证正反面,合成 PNG 并上传至派单附件
*
* @param dispatchId 派单ID
* @param relationType 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图
*/
R
<
TAttaInfo
>
generateIdCardImage
(
String
dispatchId
,
String
relationType
);
}
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/service/impl/DispatchIdCardServiceImpl.java
0 → 100644
View file @
54918760
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
social
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.yifu.cloud.plus.v1.yifu.archives.vo.IdCardAttaVo
;
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.dapr.util.ArchivesDaprUtil
;
import
com.yifu.cloud.plus.v1.yifu.social.constants.DispatchConstants
;
import
com.yifu.cloud.plus.v1.yifu.social.entity.TAttaInfo
;
import
com.yifu.cloud.plus.v1.yifu.social.entity.TDispatchInfo
;
import
com.yifu.cloud.plus.v1.yifu.social.service.DispatchIdCardService
;
import
com.yifu.cloud.plus.v1.yifu.social.service.TAttaInfoService
;
import
com.yifu.cloud.plus.v1.yifu.social.service.TDispatchInfoService
;
import
com.yifu.cloud.plus.v1.yifu.social.util.ContractPdfUtil
;
import
com.yifu.cloud.plus.v1.yifu.social.util.IdCardMergeUtil
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.log4j.Log4j2
;
import
org.apache.commons.io.IOUtils
;
import
org.springframework.stereotype.Service
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.net.URL
;
import
java.time.LocalDateTime
;
import
java.util.List
;
/**
* 派单身份证合成附件服务实现
*/
@Log4j2
@Service
@RequiredArgsConstructor
public
class
DispatchIdCardServiceImpl
implements
DispatchIdCardService
{
private
final
TDispatchInfoService
tDispatchInfoService
;
private
final
ArchivesDaprUtil
archivesDaprUtil
;
private
final
OSSUtil
ossUtil
;
private
final
TAttaInfoService
tAttaInfoService
;
// 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图
private
static
final
String
S_15
=
"15"
;
private
static
final
String
S_16
=
"16"
;
private
static
final
String
S_17
=
"17"
;
private
static
final
String
S_18
=
"18"
;
// relationType 15:社保-档案身份证合成图;16:医保-档案身份证合成图;17:社保-档案合同合成图;18:医保-档案合同合成图
@Override
public
R
<
TAttaInfo
>
generateIdCardImage
(
String
dispatchId
,
String
relationType
)
{
if
(
Common
.
isEmpty
(
dispatchId
)
||
Common
.
isEmpty
(
relationType
))
{
return
R
.
failed
(
CommonConstants
.
PARAM_IS_NOT_ERROR
);
}
if
(!
S_15
.
equals
(
relationType
)
&&
!
S_16
.
equals
(
relationType
)
&&
!
S_17
.
equals
(
relationType
)
&&
!
S_18
.
equals
(
relationType
))
{
return
R
.
failed
(
"relationType错误,你传的是:"
+
relationType
);
}
try
{
TDispatchInfo
dispatch
=
tDispatchInfoService
.
getById
(
dispatchId
);
if
(
dispatch
==
null
)
{
return
R
.
failed
(
CommonConstants
.
NO_DATA_TO_HANDLE
);
}
String
fileName
=
dispatch
.
getEmpName
()
+
"_身份证合成.png"
;
if
(
S_17
.
equals
(
relationType
)
||
S_18
.
equals
(
relationType
))
{
fileName
=
dispatch
.
getEmpName
()
+
"_合同转化.png"
;
}
TAttaInfo
attaInfo
=
getExistingAtta
(
dispatchId
,
relationType
);
// 存在直接返回
// 策略1:当前派单,如果已有对应的生成图片,不会再次新生成,需要手动删除后,再次打开审核界面,才会再次拉取生成。
if
(
attaInfo
!=
null
&&
Common
.
isNotNull
(
attaInfo
.
getAttaSrc
()))
{
URL
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
if
(
url
!=
null
)
{
attaInfo
.
setAttaUrl
(
url
.
toString
());
}
return
R
.
ok
(
attaInfo
);
}
else
{
// 策略2:社保、医保的身份证,是同一个,如果社保有,医保就复制,不抓取生成,医保有,社保没有,也是复制。
//合同同理。
String
otherRelationType
;
switch
(
relationType
)
{
case
S_15:
otherRelationType
=
S_16
;
break
;
case
S_16:
otherRelationType
=
S_15
;
break
;
case
S_17:
otherRelationType
=
S_18
;
break
;
default
:
otherRelationType
=
S_17
;
break
;
}
TAttaInfo
otherAttaInfo
=
getExistingAtta
(
dispatchId
,
otherRelationType
);
if
(
otherAttaInfo
!=
null
&&
Common
.
isNotNull
(
otherAttaInfo
.
getAttaSrc
()))
{
attaInfo
=
buildAttaInfo
(
fileName
,
otherAttaInfo
.
getAttaSrc
(),
otherAttaInfo
.
getAttaSize
(),
relationType
,
dispatchId
);
attaInfo
=
tAttaInfoService
.
add
(
attaInfo
);
URL
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
if
(
url
!=
null
)
{
attaInfo
.
setAttaUrl
(
url
.
toString
());
}
return
R
.
ok
(
attaInfo
);
}
}
if
(
S_15
.
equals
(
relationType
)
||
S_16
.
equals
(
relationType
))
{
// 身份证
return
getCardAttaInfoR
(
dispatchId
,
relationType
,
dispatch
,
fileName
);
}
else
{
// 合同
return
getContractAttaInfoR
(
dispatchId
,
relationType
,
dispatch
,
fileName
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"派单身份证或合同合成失败, dispatchId={}, relationType={}"
,
dispatchId
,
relationType
,
e
);
return
R
.
failed
(
DispatchConstants
.
MSG_MERGE_FAILED
);
}
}
// 获取合同图片:
// 审核类型:自动化派单-无需审核
// 归档状态:已归档
// 合同状态:可用。
// 身份证+ 项目编码。
// 获取pdf类型的合同,转化为图片,压缩4M以下。
private
R
<
TAttaInfo
>
getContractAttaInfoR
(
String
dispatchId
,
String
relationType
,
TDispatchInfo
dispatch
,
String
fileName
)
throws
Exception
{
TAttaInfo
attaInfo
;
IdCardAttaVo
contractAtta
=
fetchContractAtta
(
dispatch
);
if
(
contractAtta
==
null
||
Common
.
isEmpty
(
contractAtta
.
getContractAttaSrc
())
||
Common
.
isEmpty
(
contractAtta
.
getContractAttaName
()))
{
return
R
.
failed
(
DispatchConstants
.
MSG_NO_CONTRACT
);
}
byte
[]
contractBytes
=
downloadOssObject
(
contractAtta
.
getContractAttaSrc
());
byte
[]
mergedBytes
=
ContractPdfUtil
.
convertAllPagesAndCompress
(
contractBytes
);
String
key
=
"dispatch/contract/"
+
dispatchId
+
"/"
+
System
.
currentTimeMillis
()
+
"_contract.png"
;
boolean
uploaded
=
ossUtil
.
uploadFileByStream
(
new
ByteArrayInputStream
(
mergedBytes
),
key
,
null
);
if
(!
uploaded
)
{
return
R
.
failed
(
DispatchConstants
.
MSG_MERGE_FAILED
);
}
attaInfo
=
buildAttaInfo
(
fileName
,
key
,
mergedBytes
.
length
,
relationType
,
dispatchId
);
attaInfo
=
tAttaInfoService
.
add
(
attaInfo
);
URL
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
if
(
url
!=
null
)
{
attaInfo
.
setAttaUrl
(
url
.
toString
());
}
return
R
.
ok
(
attaInfo
);
}
// 获取身份证图片
private
R
<
TAttaInfo
>
getCardAttaInfoR
(
String
dispatchId
,
String
relationType
,
TDispatchInfo
dispatch
,
String
fileName
)
throws
Exception
{
TAttaInfo
attaInfo
;
IdCardAttaVo
idCardAtta
=
fetchIdCardAtta
(
dispatch
);
if
(
idCardAtta
==
null
||
Common
.
isEmpty
(
idCardAtta
.
getFrontAttaSrc
())
||
Common
.
isEmpty
(
idCardAtta
.
getBackAttaSrc
()))
{
return
R
.
failed
(
DispatchConstants
.
MSG_NO_ID_CARD
);
}
byte
[]
frontBytes
=
downloadOssObject
(
idCardAtta
.
getFrontAttaSrc
());
byte
[]
backBytes
=
downloadOssObject
(
idCardAtta
.
getBackAttaSrc
());
byte
[]
mergedBytes
=
IdCardMergeUtil
.
mergeAndCompress
(
frontBytes
,
backBytes
);
String
key
=
"dispatch/idCard/"
+
dispatchId
+
"/"
+
System
.
currentTimeMillis
()
+
"_idcard.png"
;
boolean
uploaded
=
ossUtil
.
uploadFileByStream
(
new
ByteArrayInputStream
(
mergedBytes
),
key
,
null
);
if
(!
uploaded
)
{
return
R
.
failed
(
DispatchConstants
.
MSG_MERGE_FAILED
);
}
attaInfo
=
buildAttaInfo
(
fileName
,
key
,
mergedBytes
.
length
,
relationType
,
dispatchId
);
attaInfo
=
tAttaInfoService
.
add
(
attaInfo
);
URL
url
=
ossUtil
.
getObjectUrl
(
null
,
attaInfo
.
getAttaSrc
());
if
(
url
!=
null
)
{
attaInfo
.
setAttaUrl
(
url
.
toString
());
}
return
R
.
ok
(
attaInfo
);
}
private
IdCardAttaVo
fetchIdCardAtta
(
TDispatchInfo
dispatch
)
{
if
(
Common
.
isEmpty
(
dispatch
.
getEmpIdcard
()))
{
return
null
;
}
R
<
IdCardAttaVo
>
res
=
archivesDaprUtil
.
getIdCardAttaByEmpIdCard
(
dispatch
.
getEmpIdcard
());
return
res
==
null
?
null
:
res
.
getData
();
}
private
IdCardAttaVo
fetchContractAtta
(
TDispatchInfo
dispatch
)
{
if
(
Common
.
isEmpty
(
dispatch
.
getEmpIdcard
())
&&
Common
.
isEmpty
(
dispatch
.
getSettleDomainCode
()))
{
return
null
;
}
R
<
IdCardAttaVo
>
res
=
archivesDaprUtil
.
getContractAttaByEmpIdCard
(
dispatch
.
getEmpIdcard
(),
dispatch
.
getSettleDomainCode
());
return
res
==
null
?
null
:
res
.
getData
();
}
private
byte
[]
downloadOssObject
(
String
attaSrc
)
throws
Exception
{
URL
url
=
ossUtil
.
getObjectUrl
(
null
,
attaSrc
);
if
(
url
==
null
)
{
throw
new
IllegalStateException
(
"oss url is null"
);
}
try
(
InputStream
in
=
url
.
openStream
())
{
return
IOUtils
.
toByteArray
(
in
);
}
}
private
TAttaInfo
getExistingAtta
(
String
dispatchId
,
String
relationType
)
{
List
<
TAttaInfo
>
oldList
=
tAttaInfoService
.
list
(
Wrappers
.<
TAttaInfo
>
query
().
lambda
()
.
eq
(
TAttaInfo:
:
getDomainId
,
dispatchId
)
.
eq
(
TAttaInfo:
:
getRelationType
,
relationType
));
if
(
Common
.
isNotNull
(
oldList
))
{
return
oldList
.
get
(
0
);
}
return
null
;
}
private
TAttaInfo
buildAttaInfo
(
String
fileName
,
String
key
,
long
fileSize
,
String
relationType
,
String
dispatchId
)
{
TAttaInfo
attaInfo
=
new
TAttaInfo
();
attaInfo
.
setAttaName
(
fileName
);
attaInfo
.
setAttaSize
(
fileSize
);
attaInfo
.
setAttaSrc
(
key
);
attaInfo
.
setAttaType
(
".png"
);
attaInfo
.
setRelationType
(
relationType
);
attaInfo
.
setDomainId
(
dispatchId
);
attaInfo
.
setCreateTime
(
LocalDateTime
.
now
());
return
attaInfo
;
}
}
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/service/impl/TSocialFriendPushServiceImpl.java
View file @
54918760
...
@@ -521,9 +521,13 @@ public class TSocialFriendPushServiceImpl extends ServiceImpl<TSocialFriendMappe
...
@@ -521,9 +521,13 @@ public class TSocialFriendPushServiceImpl extends ServiceImpl<TSocialFriendMappe
imgUrl
=
socialFriendConfig
.
uploadPng
(
restTemplate
,
attaInfo
.
getAttaName
(),
base64String
,
backLog
);
imgUrl
=
socialFriendConfig
.
uploadPng
(
restTemplate
,
attaInfo
.
getAttaName
(),
base64String
,
backLog
);
tSocialFriendBackLogService
.
save
(
backLog
);
tSocialFriendBackLogService
.
save
(
backLog
);
if
(
Common
.
isNotNull
(
imgUrl
)){
if
(
Common
.
isNotNull
(
imgUrl
)){
if
(
Common
.
isEmpty
(
attaInfo
.
getRelationType
())
||
CommonConstants
.
TWO_STRING
.
equals
(
attaInfo
.
getRelationType
()))
{
if
(
Common
.
isEmpty
(
attaInfo
.
getRelationType
())
||
CommonConstants
.
TWO_STRING
.
equals
(
attaInfo
.
getRelationType
())
||
DispatchConstants
.
ATTA_TYPE_ID_CARD_MERGE_YGS
.
equals
(
attaInfo
.
getRelationType
())
||
DispatchConstants
.
ATTA_TYPE_CONTRACT_MERGE_YGS
.
equals
(
attaInfo
.
getRelationType
()))
{
imgListYgs
.
add
(
imgUrl
);
imgListYgs
.
add
(
imgUrl
);
}
else
if
(
CommonConstants
.
THREE_STRING
.
equals
(
attaInfo
.
getRelationType
()))
{
}
else
if
(
CommonConstants
.
THREE_STRING
.
equals
(
attaInfo
.
getRelationType
())
||
DispatchConstants
.
ATTA_TYPE_ID_CARD_MERGE_YSD
.
equals
(
attaInfo
.
getRelationType
())
||
DispatchConstants
.
ATTA_TYPE_CONTRACT_MERGE_YSD
.
equals
(
attaInfo
.
getRelationType
()))
{
imgListYsd
.
add
(
imgUrl
);
imgListYsd
.
add
(
imgUrl
);
}
else
if
(
CommonConstants
.
FOUR_STRING
.
equals
(
attaInfo
.
getRelationType
())
&&
!
isAutoYgsHmc
)
{
}
else
if
(
CommonConstants
.
FOUR_STRING
.
equals
(
attaInfo
.
getRelationType
())
&&
!
isAutoYgsHmc
)
{
vo
.
setQyzgshbxzyhmc
(
imgUrl
);
vo
.
setQyzgshbxzyhmc
(
imgUrl
);
...
...
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/util/ContractPdfUtil.java
0 → 100644
View file @
54918760
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
social
.
util
;
import
org.apache.pdfbox.pdmodel.PDDocument
;
import
org.apache.pdfbox.rendering.ImageType
;
import
org.apache.pdfbox.rendering.PDFRenderer
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 合同 PDF 全页转 PNG 并压缩
*/
public
final
class
ContractPdfUtil
{
private
static
final
float
PDF_RENDER_DPI_BASE
=
150
F
;
private
static
float
resolveRenderDpi
(
int
pageCount
)
{
if
(
pageCount
<=
3
)
{
return
PDF_RENDER_DPI_BASE
;
}
if
(
pageCount
<=
8
)
{
return
120
F
;
}
if
(
pageCount
<=
15
)
{
return
96
F
;
}
return
72
F
;
}
public
static
byte
[]
convertAllPagesAndCompress
(
byte
[]
pdfBytes
)
throws
IOException
{
if
(
pdfBytes
==
null
||
pdfBytes
.
length
==
0
)
{
throw
new
IOException
(
"pdf data is empty"
);
}
try
(
PDDocument
document
=
PDDocument
.
load
(
new
ByteArrayInputStream
(
pdfBytes
)))
{
int
pageCount
=
document
.
getNumberOfPages
();
if
(
pageCount
<=
0
)
{
throw
new
IOException
(
"pdf has no pages"
);
}
float
dpi
=
resolveRenderDpi
(
pageCount
);
PDFRenderer
renderer
=
new
PDFRenderer
(
document
);
List
<
BufferedImage
>
pages
=
new
ArrayList
<>(
pageCount
);
for
(
int
i
=
0
;
i
<
pageCount
;
i
++)
{
pages
.
add
(
renderer
.
renderImageWithDPI
(
i
,
dpi
,
ImageType
.
RGB
));
}
return
IdCardMergeUtil
.
mergeVerticalAndCompress
(
pages
);
}
}
}
yifu-social/yifu-social-biz/src/main/java/com/yifu/cloud/plus/v1/yifu/social/util/IdCardMergeUtil.java
0 → 100644
View file @
54918760
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
social
.
util
;
import
javax.imageio.ImageIO
;
import
java.awt.Color
;
import
java.awt.Graphics2D
;
import
java.awt.RenderingHints
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.util.Arrays
;
import
java.util.List
;
/**
* 图片纵向合成并压缩为 PNG
*/
public
final
class
IdCardMergeUtil
{
private
static
final
long
MAX_SIZE
=
4L
*
1024
*
1024
;
/** 宽度下限,多页纵向合成时以宽度为缩放基准 */
private
static
final
int
MIN_WIDTH
=
50
;
private
static
final
int
MAX_COMPRESS_ATTEMPTS
=
25
;
private
IdCardMergeUtil
()
{
}
public
static
byte
[]
mergeAndCompress
(
byte
[]
frontBytes
,
byte
[]
backBytes
)
throws
IOException
{
BufferedImage
front
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
frontBytes
));
BufferedImage
back
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
backBytes
));
if
(
front
==
null
||
back
==
null
)
{
throw
new
IOException
(
"合成图片,但是没有图片数据"
);
}
return
mergeVerticalAndCompress
(
Arrays
.
asList
(
front
,
back
));
}
public
static
byte
[]
mergeVerticalAndCompress
(
List
<
BufferedImage
>
images
)
throws
IOException
{
if
(
images
==
null
||
images
.
isEmpty
())
{
throw
new
IOException
(
"合成身份证或转化合同图片,但是没有图片数据"
);
}
return
compressToMaxSize
(
mergeVertical
(
images
));
}
private
static
BufferedImage
mergeVertical
(
List
<
BufferedImage
>
images
)
{
if
(
images
.
size
()
==
1
)
{
return
images
.
get
(
0
);
}
int
targetWidth
=
0
;
int
totalHeight
=
0
;
for
(
BufferedImage
image
:
images
)
{
targetWidth
=
Math
.
max
(
targetWidth
,
image
.
getWidth
());
}
List
<
BufferedImage
>
scaledImages
=
new
java
.
util
.
ArrayList
<>(
images
.
size
());
for
(
BufferedImage
image
:
images
)
{
BufferedImage
scaled
=
scaleToWidth
(
image
,
targetWidth
);
scaledImages
.
add
(
scaled
);
totalHeight
+=
scaled
.
getHeight
();
}
BufferedImage
combined
=
new
BufferedImage
(
targetWidth
,
totalHeight
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g
=
combined
.
createGraphics
();
try
{
g
.
setColor
(
Color
.
WHITE
);
g
.
fillRect
(
0
,
0
,
targetWidth
,
totalHeight
);
g
.
setRenderingHint
(
RenderingHints
.
KEY_INTERPOLATION
,
RenderingHints
.
VALUE_INTERPOLATION_BILINEAR
);
int
y
=
0
;
for
(
BufferedImage
scaled
:
scaledImages
)
{
g
.
drawImage
(
scaled
,
0
,
y
,
null
);
y
+=
scaled
.
getHeight
();
}
}
finally
{
g
.
dispose
();
}
return
combined
;
}
private
static
BufferedImage
scaleToWidth
(
BufferedImage
image
,
int
targetWidth
)
{
if
(
image
.
getWidth
()
==
targetWidth
)
{
return
image
;
}
int
targetHeight
=
(
int
)
((
double
)
image
.
getHeight
()
/
image
.
getWidth
()
*
targetWidth
);
BufferedImage
scaled
=
new
BufferedImage
(
targetWidth
,
targetHeight
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g
=
scaled
.
createGraphics
();
try
{
g
.
setRenderingHint
(
RenderingHints
.
KEY_INTERPOLATION
,
RenderingHints
.
VALUE_INTERPOLATION_BILINEAR
);
g
.
drawImage
(
image
,
0
,
0
,
targetWidth
,
targetHeight
,
null
);
}
finally
{
g
.
dispose
();
}
return
scaled
;
}
private
static
byte
[]
compressToMaxSize
(
BufferedImage
image
)
throws
IOException
{
BufferedImage
current
=
image
;
for
(
int
attempt
=
0
;
attempt
<
MAX_COMPRESS_ATTEMPTS
;
attempt
++)
{
byte
[]
data
=
writePng
(
current
);
if
(
data
.
length
<=
MAX_SIZE
)
{
return
data
;
}
if
(
current
.
getWidth
()
<=
MIN_WIDTH
)
{
throw
new
IOException
(
"压缩时,宽度小于60px后仍大于4MB,无法继续压缩,请检查原件"
);
}
double
sizeRatio
=
(
double
)
MAX_SIZE
/
data
.
length
;
// PNG 体积与像素面积近似成正比,按面积比例开方估算缩放系数
double
scale
=
Math
.
sqrt
(
sizeRatio
)
*
0.92
D
;
scale
=
Math
.
min
(
scale
,
0.85
D
);
scale
=
Math
.
max
(
scale
,
0.55
D
);
int
newWidth
=
Math
.
max
(
MIN_WIDTH
,
(
int
)
(
current
.
getWidth
()
*
scale
));
int
newHeight
=
Math
.
max
(
1
,
(
int
)
(
current
.
getHeight
()
*
((
double
)
newWidth
/
current
.
getWidth
())));
if
(
newWidth
==
current
.
getWidth
()
&&
newHeight
==
current
.
getHeight
())
{
newWidth
=
Math
.
max
(
MIN_WIDTH
,
(
int
)
(
current
.
getWidth
()
*
0.85
D
));
newHeight
=
Math
.
max
(
1
,
(
int
)
(
current
.
getHeight
()
*
0.85
D
));
}
current
=
scaleImage
(
current
,
newWidth
,
newHeight
);
}
throw
new
IOException
(
"压缩时,宽度小于60px后仍大于4MB,无法继续压缩,请检查原件!"
);
}
private
static
byte
[]
writePng
(
BufferedImage
image
)
throws
IOException
{
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
ImageIO
.
write
(
image
,
"png"
,
baos
);
return
baos
.
toByteArray
();
}
private
static
BufferedImage
scaleImage
(
BufferedImage
image
,
int
newWidth
,
int
newHeight
)
{
BufferedImage
resized
=
new
BufferedImage
(
newWidth
,
newHeight
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g
=
resized
.
createGraphics
();
try
{
g
.
setRenderingHint
(
RenderingHints
.
KEY_INTERPOLATION
,
RenderingHints
.
VALUE_INTERPOLATION_BILINEAR
);
g
.
drawImage
(
image
,
0
,
0
,
newWidth
,
newHeight
,
null
);
}
finally
{
g
.
dispose
();
}
return
resized
;
}
}
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