Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf
Overview
Overview
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-csf
Commits
4bf8eaf1
Commit
4bf8eaf1
authored
Aug 03, 2026
by
jianan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
操作日志1
parent
dd86ab31
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1303 additions
and
13 deletions
+1303
-13
yd-csf-api/src/main/java/com/yd/csf/api/controller/AuditLogController.java
+75
-0
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditContext.java
+47
-0
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditContextHolder.java
+23
-0
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditHelper.java
+225
-0
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditService.java
+136
-0
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditTemplate.java
+72
-0
yd-csf-service/src/main/java/com/yd/csf/service/audit/FieldLabelResolver.java
+64
-0
yd-csf-service/src/main/java/com/yd/csf/service/component/CommissionAsyncService.java
+135
-13
yd-csf-service/src/main/java/com/yd/csf/service/dao/AuditLogDataChangeMapper.java
+15
-0
yd-csf-service/src/main/java/com/yd/csf/service/dao/AuditLogDataSnapshotMapper.java
+15
-0
yd-csf-service/src/main/java/com/yd/csf/service/dao/AuditLogMapper.java
+15
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/Commission.java
+2
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/CommissionExpected.java
+2
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/ExpectedFortune.java
+2
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/Fortune.java
+2
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/SysOperDataChange.java
+72
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/SysOperDataSnapshot.java
+52
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/SysOperLog.java
+112
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/AuditLogDataChangeService.java
+13
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/AuditLogDataSnapshotService.java
+13
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/AuditLogService.java
+13
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/AuditLogDataChangeServiceImpl.java
+25
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/AuditLogDataSnapshotServiceImpl.java
+25
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/AuditLogServiceImpl.java
+25
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/CommissionServiceImpl.java
+0
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/FortuneServiceImpl.java
+39
-0
yd-csf-service/src/main/resources/mappers/AuditLogDataChangeMapper.xml
+26
-0
yd-csf-service/src/main/resources/mappers/AuditLogDataSnapshotMapper.xml
+22
-0
yd-csf-service/src/main/resources/mappers/AuditLogMapper.xml
+36
-0
No files found.
yd-csf-api/src/main/java/com/yd/csf/api/controller/AuditLogController.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
api
.
controller
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yd.common.result.Result
;
import
com.yd.csf.api.dto.AuditLogQueryRequest
;
import
com.yd.csf.service.model.SysOperDataChange
;
import
com.yd.csf.service.model.SysOperDataSnapshot
;
import
com.yd.csf.service.model.SysOperLog
;
import
com.yd.csf.service.service.AuditLogDataChangeService
;
import
com.yd.csf.service.service.AuditLogDataSnapshotService
;
import
com.yd.csf.service.service.AuditLogService
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.RequiredArgsConstructor
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.Resource
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
@RestController
@RequestMapping
(
"/auditlog"
)
@Tag
(
name
=
"审计日志"
)
@RequiredArgsConstructor
public
class
AuditLogController
{
@Resource
private
AuditLogService
operLogService
;
@Resource
private
AuditLogDataSnapshotService
snapshotService
;
@Resource
private
AuditLogDataChangeService
changeService
;
@PostMapping
(
"/log/page"
)
@Operation
(
summary
=
"操作日志分页查询"
)
public
Result
<
Page
<
SysOperLog
>>
page
(
@RequestBody
AuditLogQueryRequest
request
)
{
LambdaQueryWrapper
<
SysOperLog
>
wrapper
=
new
LambdaQueryWrapper
<
SysOperLog
>()
.
eq
(
StringUtils
.
isNotBlank
(
request
.
getModule
()),
SysOperLog:
:
getModule
,
request
.
getModule
())
.
eq
(
StringUtils
.
isNotBlank
(
request
.
getOperName
()),
SysOperLog:
:
getOperName
,
request
.
getOperName
())
.
eq
(
request
.
getStatus
()
!=
null
,
SysOperLog:
:
getStatus
,
request
.
getStatus
())
.
ge
(
StringUtils
.
isNotBlank
(
request
.
getStartTime
()),
SysOperLog:
:
getOperTime
,
request
.
getStartTime
())
.
le
(
StringUtils
.
isNotBlank
(
request
.
getEndTime
()),
SysOperLog:
:
getOperTime
,
request
.
getEndTime
())
.
orderByDesc
(
SysOperLog:
:
getOperTime
);
Page
<
SysOperLog
>
page
=
operLogService
.
page
(
new
Page
<>(
request
.
getPageNo
(),
request
.
getPageSize
()),
wrapper
);
return
Result
.
success
(
page
);
}
@GetMapping
(
"/log/detail"
)
@Operation
(
summary
=
"审计详情查询"
)
public
Result
<
Map
<
String
,
Object
>>
detail
(
@RequestParam
String
requestId
)
{
if
(
StringUtils
.
isBlank
(
requestId
))
{
return
Result
.
success
(
null
);
}
SysOperLog
operLog
=
operLogService
.
getOne
(
new
LambdaQueryWrapper
<
SysOperLog
>().
eq
(
SysOperLog:
:
getRequestId
,
requestId
));
List
<
SysOperDataSnapshot
>
snapshots
=
snapshotService
.
list
(
new
LambdaQueryWrapper
<
SysOperDataSnapshot
>().
eq
(
SysOperDataSnapshot:
:
getRequestId
,
requestId
));
List
<
SysOperDataChange
>
changes
=
changeService
.
list
(
new
LambdaQueryWrapper
<
SysOperDataChange
>().
eq
(
SysOperDataChange:
:
getRequestId
,
requestId
));
Map
<
String
,
Object
>
result
=
new
HashMap
<>();
result
.
put
(
"operLog"
,
operLog
);
result
.
put
(
"snapshots"
,
snapshots
);
result
.
put
(
"changes"
,
changes
);
return
Result
.
success
(
result
);
}
}
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditContext.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
audit
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.Date
;
@Data
@Accessors
(
chain
=
true
)
public
class
AuditContext
{
private
String
requestId
;
private
String
module
;
private
Integer
businessType
;
private
String
method
;
private
String
content
;
private
Long
businessId
;
private
Integer
operationType
;
private
Long
userId
;
private
String
operName
;
private
String
deptName
;
private
String
operUrl
;
private
String
operIp
;
private
String
operLocation
;
private
String
operParam
;
private
String
jsonResult
;
private
Integer
status
;
private
String
errorMsg
;
private
Date
operTime
;
}
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditContextHolder.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
audit
;
public
class
AuditContextHolder
{
private
static
final
ThreadLocal
<
AuditContext
>
CONTEXT
=
new
ThreadLocal
<>();
public
static
void
set
(
AuditContext
context
)
{
CONTEXT
.
set
(
context
);
}
public
static
AuditContext
get
()
{
return
CONTEXT
.
get
();
}
public
static
String
getRequestId
()
{
AuditContext
ctx
=
CONTEXT
.
get
();
return
ctx
!=
null
?
ctx
.
getRequestId
()
:
null
;
}
public
static
void
clear
()
{
CONTEXT
.
remove
();
}
}
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditHelper.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
audit
;
import
cn.hutool.core.collection.CollUtil
;
import
com.google.gson.ExclusionStrategy
;
import
com.google.gson.FieldAttributes
;
import
com.google.gson.Gson
;
import
com.google.gson.GsonBuilder
;
import
com.yd.csf.service.annotation.Auditable
;
import
com.yd.csf.service.model.SysOperDataChange
;
import
com.yd.csf.service.model.SysOperDataSnapshot
;
import
com.yd.csf.service.service.AuditLogDataChangeService
;
import
com.yd.csf.service.service.AuditLogDataSnapshotService
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
java.lang.reflect.Field
;
import
java.util.*
;
@Slf4j
@Component
@RequiredArgsConstructor
public
class
AuditHelper
{
private
final
AuditLogDataSnapshotService
snapshotService
;
private
final
AuditLogDataChangeService
changeService
;
private
final
FieldLabelResolver
fieldLabelResolver
;
private
static
final
Set
<
String
>
EXCLUDED_FIELDS
=
new
HashSet
<>(
Arrays
.
asList
(
"id"
,
"createTime"
,
"updateTime"
,
"creatorId"
,
"creatorName"
,
"updaterId"
,
"updaterName"
,
"isDeleted"
,
"serialVersionUID"
));
private
static
final
Gson
GSON
=
new
GsonBuilder
()
.
addSerializationExclusionStrategy
(
new
ExclusionStrategy
()
{
@Override
public
boolean
shouldSkipField
(
FieldAttributes
f
)
{
return
EXCLUDED_FIELDS
.
contains
(
f
.
getName
());
}
@Override
public
boolean
shouldSkipClass
(
Class
<?>
clazz
)
{
return
false
;
}
})
.
create
();
/**
* 记录数据变更。
*
* @param tableName 表名
* @param beforeMap 变更前的数据,key 为主键值,value 为实体对象(INSERT 时为 null)
* @param afterMap 变更后的数据,key 为主键值,value 为实体对象(DELETE 时为 null)
* @param ctx 审计上下文
*/
public
void
record
(
String
tableName
,
Map
<
String
,
?>
beforeMap
,
Map
<
String
,
?>
afterMap
,
AuditContext
ctx
)
{
if
(
beforeMap
==
null
&&
afterMap
==
null
)
{
return
;
}
Class
<?>
entityClass
=
getEntityClass
(
beforeMap
,
afterMap
);
if
(
entityClass
==
null
)
{
log
.
warn
(
"无法确定实体类型,跳过审计记录: table={}"
,
tableName
);
return
;
}
Auditable
auditable
=
entityClass
.
getAnnotation
(
Auditable
.
class
);
if
(
auditable
==
null
)
{
throw
new
IllegalArgumentException
(
"实体类 "
+
entityClass
.
getName
()
+
" 缺少 @Auditable 注解"
);
}
List
<
Field
>
diffFields
=
getDiffFields
(
entityClass
);
Set
<
String
>
allIds
=
new
LinkedHashSet
<>();
if
(
beforeMap
!=
null
)
allIds
.
addAll
(
beforeMap
.
keySet
());
if
(
afterMap
!=
null
)
allIds
.
addAll
(
afterMap
.
keySet
());
List
<
SysOperDataSnapshot
>
snapshots
=
new
ArrayList
<>();
List
<
SysOperDataChange
>
changes
=
new
ArrayList
<>();
Date
now
=
new
Date
();
for
(
String
recordId
:
allIds
)
{
Object
before
=
beforeMap
!=
null
?
beforeMap
.
get
(
recordId
)
:
null
;
Object
after
=
afterMap
!=
null
?
afterMap
.
get
(
recordId
)
:
null
;
String
beforeJson
=
before
!=
null
?
GSON
.
toJson
(
before
)
:
null
;
String
afterJson
=
after
!=
null
?
GSON
.
toJson
(
after
)
:
null
;
boolean
isInsert
=
before
==
null
&&
after
!=
null
;
boolean
isDelete
=
before
!=
null
&&
after
==
null
;
String
changeType
=
isInsert
?
"ADD"
:
(
isDelete
?
"DELETE"
:
"MODIFY"
);
SysOperDataSnapshot
snapshot
=
new
SysOperDataSnapshot
();
snapshot
.
setRequestId
(
ctx
.
getRequestId
());
snapshot
.
setTableName
(
tableName
);
snapshot
.
setRecordId
(
recordId
);
snapshot
.
setBeforeJson
(
beforeJson
);
snapshot
.
setAfterJson
(
afterJson
);
snapshot
.
setCreateTime
(
now
);
snapshots
.
add
(
snapshot
);
if
(!
isInsert
&&
!
isDelete
&&
before
!=
null
&&
after
!=
null
)
{
for
(
Field
field
:
diffFields
)
{
try
{
field
.
setAccessible
(
true
);
Object
oldVal
=
field
.
get
(
before
);
Object
newVal
=
field
.
get
(
after
);
if
(!
Objects
.
equals
(
oldVal
,
newVal
))
{
SysOperDataChange
change
=
new
SysOperDataChange
();
change
.
setRequestId
(
ctx
.
getRequestId
());
change
.
setTableName
(
tableName
);
change
.
setRecordId
(
recordId
);
change
.
setFieldName
(
field
.
getName
());
change
.
setFieldComment
(
fieldLabelResolver
.
resolve
(
field
,
tableName
));
change
.
setOldValue
(
oldVal
!=
null
?
oldVal
.
toString
()
:
null
);
change
.
setNewValue
(
newVal
!=
null
?
newVal
.
toString
()
:
null
);
change
.
setChangeType
(
"MODIFY"
);
change
.
setCreateTime
(
now
);
changes
.
add
(
change
);
}
}
catch
(
IllegalAccessException
e
)
{
log
.
debug
(
"跳过无法访问的字段: {}"
,
field
.
getName
());
}
}
}
}
if
(
CollUtil
.
isNotEmpty
(
snapshots
))
{
snapshotService
.
saveBatch
(
snapshots
);
}
if
(
CollUtil
.
isNotEmpty
(
changes
))
{
changeService
.
saveBatch
(
changes
);
}
}
private
Class
<?>
getEntityClass
(
Map
<
String
,
?>
beforeMap
,
Map
<
String
,
?>
afterMap
)
{
if
(
beforeMap
!=
null
)
{
for
(
Object
v
:
beforeMap
.
values
())
{
if
(
v
!=
null
)
return
v
.
getClass
();
}
}
if
(
afterMap
!=
null
)
{
for
(
Object
v
:
afterMap
.
values
())
{
if
(
v
!=
null
)
return
v
.
getClass
();
}
}
return
null
;
}
private
List
<
Field
>
getDiffFields
(
Class
<?>
entityClass
)
{
List
<
Field
>
fields
=
new
ArrayList
<>();
Class
<?>
current
=
entityClass
;
while
(
current
!=
null
&&
current
!=
Object
.
class
)
{
for
(
Field
field
:
current
.
getDeclaredFields
())
{
if
(!
EXCLUDED_FIELDS
.
contains
(
field
.
getName
())
&&
!
java
.
lang
.
reflect
.
Modifier
.
isStatic
(
field
.
getModifiers
()))
{
fields
.
add
(
field
);
}
}
current
=
current
.
getSuperclass
();
}
return
fields
;
}
/**
* 对实体列表做深拷贝快照。
* 使用 Gson 序列化→反序列化做深拷贝,自动从 @Auditable.idField 读取 Map key。
*
* @param entities 实体列表,null 或空列表返回空 Map
* @param <T> 实体类型
* @return Map<业务ID, 深拷贝后的实体>
* @throws IllegalArgumentException 如果实体类缺少 @Auditable 注解
*/
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
Map
<
String
,
T
>
snapshot
(
List
<
T
>
entities
)
{
if
(
CollUtil
.
isEmpty
(
entities
))
{
return
Collections
.
emptyMap
();
}
T
first
=
entities
.
get
(
0
);
if
(
first
==
null
)
{
return
Collections
.
emptyMap
();
}
Class
<?>
entityClass
=
first
.
getClass
();
Auditable
auditable
=
entityClass
.
getAnnotation
(
Auditable
.
class
);
if
(
auditable
==
null
)
{
throw
new
IllegalArgumentException
(
"实体类 "
+
entityClass
.
getName
()
+
" 缺少 @Auditable 注解"
);
}
String
idFieldName
=
auditable
.
idField
();
Map
<
String
,
T
>
result
=
new
LinkedHashMap
<>();
for
(
T
entity
:
entities
)
{
try
{
Field
idField
=
findField
(
entityClass
,
idFieldName
);
if
(
idField
==
null
)
{
throw
new
RuntimeException
(
"实体类 "
+
entityClass
.
getName
()
+
" 中没有字段: "
+
idFieldName
);
}
idField
.
setAccessible
(
true
);
Object
idValue
=
idField
.
get
(
entity
);
if
(
idValue
==
null
)
{
log
.
warn
(
"实体 idField={} 值为 null,跳过: {}"
,
idFieldName
,
entity
);
continue
;
}
T
copy
=
(
T
)
GSON
.
fromJson
(
GSON
.
toJson
(
entity
),
entityClass
);
result
.
put
(
idValue
.
toString
(),
copy
);
}
catch
(
IllegalAccessException
e
)
{
throw
new
RuntimeException
(
"无法读取字段 "
+
idFieldName
,
e
);
}
}
return
result
;
}
private
Field
findField
(
Class
<?>
clazz
,
String
fieldName
)
{
Class
<?>
current
=
clazz
;
while
(
current
!=
null
&&
current
!=
Object
.
class
)
{
try
{
return
current
.
getDeclaredField
(
fieldName
);
}
catch
(
NoSuchFieldException
e
)
{
current
=
current
.
getSuperclass
();
}
}
return
null
;
}
}
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditService.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
audit
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.csf.service.model.SysOperLog
;
import
com.yd.csf.service.service.AuditLogService
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Date
;
import
java.util.UUID
;
@Slf4j
@Component
@RequiredArgsConstructor
public
class
AuditService
{
private
final
AuditLogService
operLogService
;
/**
* 开始审计,创建新的审计上下文。
*
* @param module 业务模块
* @param businessType 业务类型
* @param content 操作描述
* @return requestId
*/
public
String
begin
(
String
module
,
Integer
businessType
,
String
content
)
{
String
requestId
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
AuditContext
ctx
=
new
AuditContext
();
ctx
.
setRequestId
(
requestId
);
ctx
.
setModule
(
module
);
ctx
.
setBusinessType
(
businessType
);
ctx
.
setContent
(
content
);
ctx
.
setOperTime
(
new
Date
());
fillRequestInfo
(
ctx
);
fillOperatorInfo
(
ctx
);
AuditContextHolder
.
set
(
ctx
);
return
requestId
;
}
/**
* 使用已有 requestId 恢复审计上下文(用于异步回调)。
*/
public
void
begin
(
String
requestId
)
{
AuditContext
ctx
=
new
AuditContext
();
ctx
.
setRequestId
(
requestId
);
ctx
.
setOperTime
(
new
Date
());
AuditContextHolder
.
set
(
ctx
);
}
/**
* 标记操作成功,写入 sys_oper_log。
*/
public
void
success
(
String
requestId
)
{
AuditContext
ctx
=
AuditContextHolder
.
get
();
if
(
ctx
==
null
)
{
return
;
}
SysOperLog
log
=
buildOperLog
(
ctx
);
log
.
setStatus
(
0
);
operLogService
.
save
(
log
);
}
/**
* 标记操作失败,写入 sys_oper_log。
*/
public
void
fail
(
String
requestId
,
String
errorMsg
)
{
AuditContext
ctx
=
AuditContextHolder
.
get
();
if
(
ctx
==
null
)
{
return
;
}
SysOperLog
log
=
buildOperLog
(
ctx
);
log
.
setStatus
(
1
);
log
.
setErrorMsg
(
errorMsg
);
operLogService
.
save
(
log
);
}
/**
* 关闭审计,清理 ThreadLocal。
*/
public
void
close
(
String
requestId
)
{
AuditContextHolder
.
clear
();
}
private
void
fillRequestInfo
(
AuditContext
ctx
)
{
try
{
ServletRequestAttributes
attrs
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
if
(
attrs
!=
null
)
{
HttpServletRequest
request
=
attrs
.
getRequest
();
ctx
.
setOperUrl
(
request
.
getRequestURI
());
ctx
.
setOperIp
(
request
.
getRemoteAddr
());
}
}
catch
(
Exception
e
)
{
log
.
debug
(
"获取请求信息失败: {}"
,
e
.
getMessage
());
}
}
private
void
fillOperatorInfo
(
AuditContext
ctx
)
{
try
{
AuthUserDto
user
=
SecurityUtil
.
getCurrentLoginUser
();
ctx
.
setUserId
(
user
.
getId
());
ctx
.
setOperName
(
user
.
getUsername
());
}
catch
(
Exception
e
)
{
log
.
debug
(
"获取操作人信息失败: {}"
,
e
.
getMessage
());
}
}
private
SysOperLog
buildOperLog
(
AuditContext
ctx
)
{
SysOperLog
log
=
new
SysOperLog
();
log
.
setRequestId
(
ctx
.
getRequestId
());
log
.
setModule
(
ctx
.
getModule
());
log
.
setBusinessType
(
ctx
.
getBusinessType
());
log
.
setMethod
(
ctx
.
getMethod
());
log
.
setContent
(
ctx
.
getContent
());
log
.
setBusinessId
(
ctx
.
getBusinessId
());
log
.
setOperationType
(
ctx
.
getOperationType
());
log
.
setUserId
(
ctx
.
getUserId
());
log
.
setOperName
(
ctx
.
getOperName
());
log
.
setDeptName
(
ctx
.
getDeptName
());
log
.
setOperUrl
(
ctx
.
getOperUrl
());
log
.
setOperIp
(
ctx
.
getOperIp
());
log
.
setOperLocation
(
ctx
.
getOperLocation
());
log
.
setOperParam
(
ctx
.
getOperParam
());
log
.
setJsonResult
(
ctx
.
getJsonResult
());
log
.
setOperTime
(
ctx
.
getOperTime
());
return
log
;
}
}
yd-csf-service/src/main/java/com/yd/csf/service/audit/AuditTemplate.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
audit
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.stereotype.Component
;
/**
* 审计生命周期编排器。
* 封装 begin → action → success/fail → close 的固定模板,调用方只需编写业务逻辑。
*
* <pre>{@code
* // INSERT 场景
* return auditTemplate.execute("来佣管理", 1, "导入入账记录", ctx -> {
* saveBatch(list);
* auditHelper.record("commission", null, toMap(list), ctx);
* return true;
* });
*
* // UPDATE 场景
* return auditTemplate.execute("应付款管理", 2, "生成可出账", ctx -> {
* Map<String, ExpectedFortune> before = auditHelper.snapshot(list);
* // ... 业务变更 ...
* Map<String, ExpectedFortune> after = auditHelper.snapshot(list);
* auditHelper.record("expected_fortune", before, after, ctx);
* return true;
* });
* }</pre>
*
* @author Zhang Jianan
*/
@Component
@RequiredArgsConstructor
public
class
AuditTemplate
{
private
final
AuditService
auditService
;
/**
* 执行带审计的操作。
* 自动处理 begin → success → close(正常路径)或 begin → fail → close(异常路径)。
* 异常会原样重新抛出,不改变异常传播链。
*
* @param module 业务模块名称
* @param businessType 业务类型
* @param content 操作描述
* @param action 业务逻辑,接收 AuditContext,返回结果
* @param <T> 返回值类型
* @return action 的返回值
*/
public
<
T
>
T
execute
(
String
module
,
Integer
businessType
,
String
content
,
AuditAction
<
T
>
action
)
{
String
requestId
=
auditService
.
begin
(
module
,
businessType
,
content
);
try
{
T
result
=
action
.
apply
(
AuditContextHolder
.
get
());
auditService
.
success
(
requestId
);
return
result
;
}
catch
(
Exception
e
)
{
auditService
.
fail
(
requestId
,
e
.
getMessage
());
throw
(
RuntimeException
)
e
;
}
finally
{
auditService
.
close
(
requestId
);
}
}
/**
* 审计操作函数式接口。
*
* @param <T> 返回值类型
*/
@FunctionalInterface
public
interface
AuditAction
<
T
>
{
T
apply
(
AuditContext
ctx
);
}
}
yd-csf-service/src/main/java/com/yd/csf/service/audit/FieldLabelResolver.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
audit
;
import
com.yd.csf.service.annotation.AuditField
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.jdbc.core.JdbcTemplate
;
import
org.springframework.stereotype.Component
;
import
java.lang.reflect.Field
;
import
java.util.Arrays
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
@Component
@RequiredArgsConstructor
public
class
FieldLabelResolver
{
private
final
JdbcTemplate
jdbcTemplate
;
private
final
Map
<
String
,
String
>
cache
=
new
ConcurrentHashMap
<>();
private
static
final
String
SQL
=
"SELECT COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?"
;
/**
* 获取字段中文名,优先级:
* 1. @AuditField.label
* 2. information_schema.COLUMNS.COLUMN_COMMENT
* 3. field 名本身
*/
public
String
resolve
(
Field
field
,
String
tableName
)
{
AuditField
auditField
=
field
.
getAnnotation
(
AuditField
.
class
);
if
(
auditField
!=
null
&&
!
auditField
.
label
().
isEmpty
())
{
return
auditField
.
label
();
}
String
columnName
=
camelToUnderscore
(
field
.
getName
());
String
cacheKey
=
tableName
+
"."
+
columnName
;
String
comment
=
cache
.
computeIfAbsent
(
cacheKey
,
k
->
{
try
{
return
jdbcTemplate
.
queryForObject
(
SQL
,
String
.
class
,
tableName
,
columnName
);
}
catch
(
Exception
e
)
{
return
null
;
}
});
if
(
comment
!=
null
&&
!
comment
.
isEmpty
())
{
return
comment
;
}
return
field
.
getName
();
}
private
String
camelToUnderscore
(
String
camel
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
camel
.
length
();
i
++)
{
char
c
=
camel
.
charAt
(
i
);
if
(
Character
.
isUpperCase
(
c
))
{
sb
.
append
(
'_'
).
append
(
Character
.
toLowerCase
(
c
));
}
else
{
sb
.
append
(
c
);
}
}
return
sb
.
toString
();
}
}
yd-csf-service/src/main/java/com/yd/csf/service/component/CommissionAsyncService.java
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
component
;
import
cn.hutool.core.collection.CollUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.common.enums.ResultCode
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.csf.service.audit.AuditContextHolder
;
import
com.yd.csf.service.audit.AuditHelper
;
import
com.yd.csf.service.audit.AuditService
;
import
com.yd.csf.service.enums.CommissionExpectedStatusEnum
;
import
com.yd.csf.service.enums.CommissionStatusEnum
;
import
com.yd.csf.service.model.Commission
;
...
...
@@ -24,9 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
import
javax.annotation.Resource
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.*
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
...
...
@@ -39,28 +41,148 @@ public class CommissionAsyncService {
private
CommissionService
commissionService
;
@Resource
private
CommissionCompareRecordService
commissionCompareRecordService
;
@Resource
private
AuditService
auditService
;
@Resource
private
AuditHelper
auditHelper
;
// @Async("commonAsyncExecutor")
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
public
void
commissionCompareBatch
(
List
<
Commission
>
entities
)
{
// 根据是否关联保单号,来区分比对方式
List
<
Commission
>
hasPolicyNoList
=
new
ArrayList
<>();
List
<
Commission
>
noPolicyNoList
=
new
ArrayList
<>();
for
(
Commission
entity
:
entities
)
{
if
(
"U"
.
equals
(
entity
.
getCommissionBizType
()))
{
noPolicyNoList
.
add
(
entity
);
}
else
{
hasPolicyNoList
.
add
(
entity
);
// 保留旧签名兼容(无审计)
commissionCompareBatch
(
entities
,
null
);
}
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
public
void
commissionCompareBatch
(
List
<
Commission
>
entities
,
String
requestId
)
{
if
(
requestId
!=
null
)
{
auditService
.
begin
(
requestId
);
}
try
{
// 根据是否关联保单号,来区分比对方式
List
<
Commission
>
hasPolicyNoList
=
new
ArrayList
<>();
List
<
Commission
>
noPolicyNoList
=
new
ArrayList
<>();
for
(
Commission
entity
:
entities
)
{
if
(
"U"
.
equals
(
entity
.
getCommissionBizType
()))
{
noPolicyNoList
.
add
(
entity
);
}
else
{
hasPolicyNoList
.
add
(
entity
);
}
}
// 审计:收集将被修改的记录ID,拍快照
Set
<
String
>
commissionBizIds
=
new
HashSet
<>();
Set
<
String
>
expectedBizIds
=
new
HashSet
<>();
collectAffectedIds
(
hasPolicyNoList
,
noPolicyNoList
,
commissionBizIds
,
expectedBizIds
);
Map
<
String
,
Commission
>
commissionBefore
=
queryCommissionsByBizIds
(
commissionBizIds
);
Map
<
String
,
CommissionExpected
>
expectedBefore
=
queryExpectedByBizIds
(
expectedBizIds
);
// 执行比对
if
(
CollectionUtils
.
isNotEmpty
(
hasPolicyNoList
))
{
normalBatch
(
hasPolicyNoList
);
}
if
(
CollectionUtils
.
isNotEmpty
(
noPolicyNoList
))
{
noPolicyNoBatch
(
noPolicyNoList
);
}
// 审计:记录变更(不写 oper_log,主事务已写)
if
(
requestId
!=
null
)
{
Map
<
String
,
Commission
>
commissionAfter
=
queryCommissionsByBizIds
(
commissionBizIds
);
Map
<
String
,
CommissionExpected
>
expectedAfter
=
queryExpectedByBizIds
(
expectedBizIds
);
if
(
CollUtil
.
isNotEmpty
(
commissionBefore
)
&&
CollUtil
.
isNotEmpty
(
commissionAfter
))
{
auditHelper
.
record
(
"commission"
,
commissionBefore
,
commissionAfter
,
AuditContextHolder
.
get
());
}
if
(
CollUtil
.
isNotEmpty
(
expectedBefore
)
&&
CollUtil
.
isNotEmpty
(
expectedAfter
))
{
auditHelper
.
record
(
"commission_expected"
,
expectedBefore
,
expectedAfter
,
AuditContextHolder
.
get
());
}
}
}
catch
(
Exception
e
)
{
throw
e
;
}
finally
{
if
(
requestId
!=
null
)
{
auditService
.
close
(
requestId
);
}
}
}
/**
* 收集比对过程中会被修改的 commission 和 commission_expected 记录ID。
*/
private
void
collectAffectedIds
(
List
<
Commission
>
hasPolicyNoList
,
List
<
Commission
>
noPolicyNoList
,
Set
<
String
>
commissionBizIds
,
Set
<
String
>
expectedBizIds
)
{
// 新插入的 commission
for
(
Commission
entity
:
hasPolicyNoList
)
{
if
(
entity
.
getCommissionBizId
()
!=
null
)
{
commissionBizIds
.
add
(
entity
.
getCommissionBizId
());
}
}
for
(
Commission
entity
:
noPolicyNoList
)
{
if
(
entity
.
getCommissionBizId
()
!=
null
)
{
commissionBizIds
.
add
(
entity
.
getCommissionBizId
());
}
}
// normalBatch: 查询同一 expectedBizId 下的所有已存在 commission
if
(
CollectionUtils
.
isNotEmpty
(
hasPolicyNoList
))
{
normalBatch
(
hasPolicyNoList
);
List
<
String
>
commissionExpectedBizIdList
=
hasPolicyNoList
.
stream
()
.
map
(
Commission:
:
getCommissionExpectedBizId
)
.
filter
(
StringUtils:
:
isNotBlank
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
if
(
CollectionUtils
.
isNotEmpty
(
commissionExpectedBizIdList
))
{
List
<
Commission
>
existing
=
commissionService
.
lambdaQuery
()
.
in
(
Commission:
:
getCommissionExpectedBizId
,
commissionExpectedBizIdList
)
.
list
();
existing
.
forEach
(
c
->
{
if
(
c
.
getCommissionBizId
()
!=
null
)
{
commissionBizIds
.
add
(
c
.
getCommissionBizId
());
}
});
expectedBizIds
.
addAll
(
commissionExpectedBizIdList
);
}
}
// noPolicyNoBatch: 查询同一 receivableNo 的 commissionExpected
if
(
CollectionUtils
.
isNotEmpty
(
noPolicyNoList
))
{
noPolicyNoBatch
(
noPolicyNoList
);
List
<
String
>
receivableNoList
=
noPolicyNoList
.
stream
()
.
map
(
Commission:
:
getReceivableNo
)
.
filter
(
StringUtils:
:
isNotBlank
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
if
(
CollectionUtils
.
isNotEmpty
(
receivableNoList
))
{
List
<
CommissionExpected
>
expectedList
=
commissionExpectedService
.
lambdaQuery
()
.
in
(
CommissionExpected:
:
getReceivableNo
,
receivableNoList
)
.
list
();
expectedList
.
forEach
(
e
->
{
if
(
e
.
getCommissionExpectedBizId
()
!=
null
)
{
expectedBizIds
.
add
(
e
.
getCommissionExpectedBizId
());
}
});
}
}
}
private
Map
<
String
,
Commission
>
queryCommissionsByBizIds
(
Set
<
String
>
bizIds
)
{
if
(
CollectionUtils
.
isEmpty
(
bizIds
))
{
return
Collections
.
emptyMap
();
}
List
<
Commission
>
list
=
commissionService
.
lambdaQuery
()
.
in
(
Commission:
:
getCommissionBizId
,
new
ArrayList
<>(
bizIds
))
.
list
();
return
list
.
stream
().
collect
(
Collectors
.
toMap
(
Commission:
:
getCommissionBizId
,
Function
.
identity
()));
}
private
Map
<
String
,
CommissionExpected
>
queryExpectedByBizIds
(
Set
<
String
>
bizIds
)
{
if
(
CollectionUtils
.
isEmpty
(
bizIds
))
{
return
Collections
.
emptyMap
();
}
List
<
CommissionExpected
>
list
=
commissionExpectedService
.
lambdaQuery
()
.
in
(
CommissionExpected:
:
getCommissionExpectedBizId
,
new
ArrayList
<>(
bizIds
))
.
list
();
return
list
.
stream
().
collect
(
Collectors
.
toMap
(
CommissionExpected:
:
getCommissionExpectedBizId
,
Function
.
identity
()));
}
/**
* 无保单号的来佣比对
*
...
...
yd-csf-service/src/main/java/com/yd/csf/service/dao/AuditLogDataChangeMapper.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
dao
;
import
com.yd.csf.service.model.SysOperDataChange
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_data_change】的数据库操作Mapper
* @createDate 2026-07-30 14:46:28
* @Entity generator.domain.SysOperDataChange
*/
public
interface
AuditLogDataChangeMapper
extends
BaseMapper
<
SysOperDataChange
>
{
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/dao/AuditLogDataSnapshotMapper.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
dao
;
import
com.yd.csf.service.model.SysOperDataSnapshot
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_data_snapshot】的数据库操作Mapper
* @createDate 2026-07-30 14:46:24
* @Entity generator.domain.SysOperDataSnapshot
*/
public
interface
AuditLogDataSnapshotMapper
extends
BaseMapper
<
SysOperDataSnapshot
>
{
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/dao/AuditLogMapper.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
dao
;
import
com.yd.csf.service.model.SysOperLog
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_log】的数据库操作Mapper
* @createDate 2026-07-30 14:45:38
* @Entity generator.domain.SysOperLog
*/
public
interface
AuditLogMapper
extends
BaseMapper
<
SysOperLog
>
{
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/model/Commission.java
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.*
;
import
com.yd.csf.service.annotation.Auditable
;
import
lombok.Data
;
import
java.io.Serializable
;
...
...
@@ -13,6 +14,7 @@ import java.util.Date;
* @TableName commission
*/
@TableName
(
value
=
"commission"
)
@Auditable
(
table
=
"commission"
,
idField
=
"commissionBizId"
)
@Data
public
class
Commission
implements
Serializable
{
/**
...
...
yd-csf-service/src/main/java/com/yd/csf/service/model/CommissionExpected.java
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.*
;
import
com.yd.csf.service.annotation.Auditable
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
...
...
@@ -14,6 +15,7 @@ import java.util.Date;
* @TableName commission_expected
*/
@TableName
(
value
=
"commission_expected"
)
@Auditable
(
table
=
"commission_expected"
,
idField
=
"commissionExpectedBizId"
)
@Data
public
class
CommissionExpected
implements
Serializable
{
/**
...
...
yd-csf-service/src/main/java/com/yd/csf/service/model/ExpectedFortune.java
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.*
;
import
com.yd.csf.service.annotation.Auditable
;
import
lombok.Getter
;
import
lombok.Setter
;
...
...
@@ -20,6 +21,7 @@ import java.time.LocalDateTime;
@Getter
@Setter
@TableName
(
"expected_fortune"
)
@Auditable
(
table
=
"expected_fortune"
,
idField
=
"expectedFortuneBizId"
)
public
class
ExpectedFortune
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
...
...
yd-csf-service/src/main/java/com/yd/csf/service/model/Fortune.java
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.*
;
import
com.yd.csf.service.annotation.Auditable
;
import
java.math.BigDecimal
;
import
java.time.LocalDate
;
...
...
@@ -14,6 +15,7 @@ import lombok.Data;
* @TableName fortune
*/
@TableName
(
value
=
"fortune"
)
@Auditable
(
table
=
"fortune"
,
idField
=
"fortuneBizId"
)
@Data
public
class
Fortune
{
/**
...
...
yd-csf-service/src/main/java/com/yd/csf/service/model/SysOperDataChange.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.util.Date
;
import
lombok.Data
;
/**
*
* @TableName sys_oper_data_change
*/
@TableName
(
value
=
"sys_oper_data_change"
)
@Data
public
class
SysOperDataChange
{
/**
*
*/
@TableId
(
type
=
IdType
.
AUTO
)
private
Long
id
;
/**
*
*/
private
String
requestId
;
/**
* 关联 sys_oper_log.id(MP拦截器路径不设置,由request_id关联)
*/
private
Long
operLogId
;
/**
* 表名
*/
private
String
tableName
;
/**
* 记录主键
*/
private
String
recordId
;
/**
* 字段名
*/
private
String
fieldName
;
/**
* 字段中文名
*/
private
String
fieldComment
;
/**
* 变更前值
*/
private
String
oldValue
;
/**
* 变更后值
*/
private
String
newValue
;
/**
* ADD/MODIFY/DELETE
*/
private
String
changeType
;
/**
*
*/
private
Date
createTime
;
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/model/SysOperDataSnapshot.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.util.Date
;
import
lombok.Data
;
/**
*
* @TableName sys_oper_data_snapshot
*/
@TableName
(
value
=
"sys_oper_data_snapshot"
)
@Data
public
class
SysOperDataSnapshot
{
/**
*
*/
@TableId
(
type
=
IdType
.
AUTO
)
private
Long
id
;
/**
*
*/
private
String
requestId
;
/**
* 表名
*/
private
String
tableName
;
/**
* 记录主键
*/
private
String
recordId
;
/**
* 变更前完整快照
*/
private
String
beforeJson
;
/**
* 变更后完整快照
*/
private
String
afterJson
;
/**
*
*/
private
Date
createTime
;
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/model/SysOperLog.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.util.Date
;
import
lombok.Data
;
/**
*
* @TableName sys_oper_log
*/
@TableName
(
value
=
"sys_oper_log"
)
@Data
public
class
SysOperLog
{
/**
* 日志主键
*/
@TableId
(
type
=
IdType
.
AUTO
)
private
Long
id
;
/**
*
*/
private
String
requestId
;
/**
* 业务模块
*/
private
String
module
;
/**
* 业务类型 0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据
*/
private
Integer
businessType
;
/**
* 方法名称
*/
private
String
method
;
/**
* 日志内容
*/
private
String
content
;
/**
* 业务数据ID
*/
private
Long
businessId
;
/**
* 操作类型(0其它 1新增 2修改 3删除)
*/
private
Integer
operationType
;
/**
* 操作人ID
*/
private
Long
userId
;
/**
* 操作人员
*/
private
String
operName
;
/**
* 部门名称
*/
private
String
deptName
;
/**
* 请求URL
*/
private
String
operUrl
;
/**
* 主机地址
*/
private
String
operIp
;
/**
* 操作地点
*/
private
String
operLocation
;
/**
* 请求参数
*/
private
String
operParam
;
/**
* 返回参数
*/
private
String
jsonResult
;
/**
* 0成功 1失败
*/
private
Integer
status
;
/**
* 错误消息
*/
private
String
errorMsg
;
/**
* 操作时间
*/
private
Date
operTime
;
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/service/AuditLogDataChangeService.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
service
;
import
com.yd.csf.service.model.SysOperDataChange
;
import
com.baomidou.mybatisplus.extension.service.IService
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_data_change】的数据库操作Service
* @createDate 2026-07-30 14:46:28
*/
public
interface
AuditLogDataChangeService
extends
IService
<
SysOperDataChange
>
{
}
yd-csf-service/src/main/java/com/yd/csf/service/service/AuditLogDataSnapshotService.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
service
;
import
com.yd.csf.service.model.SysOperDataSnapshot
;
import
com.baomidou.mybatisplus.extension.service.IService
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_data_snapshot】的数据库操作Service
* @createDate 2026-07-30 14:46:24
*/
public
interface
AuditLogDataSnapshotService
extends
IService
<
SysOperDataSnapshot
>
{
}
yd-csf-service/src/main/java/com/yd/csf/service/service/AuditLogService.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
service
;
import
com.yd.csf.service.model.SysOperLog
;
import
com.baomidou.mybatisplus.extension.service.IService
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_log】的数据库操作Service
* @createDate 2026-07-30 14:45:38
*/
public
interface
AuditLogService
extends
IService
<
SysOperLog
>
{
}
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/AuditLogDataChangeServiceImpl.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.csf.service.model.SysOperDataChange
;
import
com.yd.csf.service.service.AuditLogDataChangeService
;
import
com.yd.csf.service.dao.AuditLogDataChangeMapper
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Propagation
;
import
org.springframework.transaction.annotation.Transactional
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_data_change】的数据库操作Service实现
* @createDate 2026-07-30 14:46:28
*/
@Service
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
public
class
AuditLogDataChangeServiceImpl
extends
ServiceImpl
<
AuditLogDataChangeMapper
,
SysOperDataChange
>
implements
AuditLogDataChangeService
{
}
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/AuditLogDataSnapshotServiceImpl.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.csf.service.model.SysOperDataSnapshot
;
import
com.yd.csf.service.service.AuditLogDataSnapshotService
;
import
com.yd.csf.service.dao.AuditLogDataSnapshotMapper
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Propagation
;
import
org.springframework.transaction.annotation.Transactional
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_data_snapshot】的数据库操作Service实现
* @createDate 2026-07-30 14:46:24
*/
@Service
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
public
class
AuditLogDataSnapshotServiceImpl
extends
ServiceImpl
<
AuditLogDataSnapshotMapper
,
SysOperDataSnapshot
>
implements
AuditLogDataSnapshotService
{
}
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/AuditLogServiceImpl.java
0 → 100644
View file @
4bf8eaf1
package
com
.
yd
.
csf
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.csf.service.model.SysOperLog
;
import
com.yd.csf.service.service.AuditLogService
;
import
com.yd.csf.service.dao.AuditLogMapper
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Propagation
;
import
org.springframework.transaction.annotation.Transactional
;
/**
* @author Zhang Jianan
* @description 针对表【sys_oper_log】的数据库操作Service实现
* @createDate 2026-07-30 14:45:38
*/
@Service
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
public
class
AuditLogServiceImpl
extends
ServiceImpl
<
AuditLogMapper
,
SysOperLog
>
implements
AuditLogService
{
}
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/CommissionServiceImpl.java
View file @
4bf8eaf1
This diff is collapsed.
Click to expand it.
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/FortuneServiceImpl.java
View file @
4bf8eaf1
...
...
@@ -18,6 +18,11 @@ import com.yd.common.exception.BusinessException;
import
com.yd.common.result.Result
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.common.utils.RedisUtil
;
import
com.yd.csf.service.audit.AuditContextHolder
;
import
com.yd.csf.service.audit.AuditHelper
;
import
com.yd.csf.service.audit.AuditService
;
import
com.yd.csf.service.audit.AuditTemplate
;
import
com.yd.csf.service.audit.AuditContext
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.enums.FortuneStatusEnum
;
import
com.yd.csf.service.model.*
;
...
...
@@ -75,6 +80,12 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
private
ApiExchangeRateFeignClient
apiExchangeRateFeignClient
;
@Resource
private
IAgentAccumulatedFycService
iAgentAccumulatedFycService
;
@Resource
private
AuditService
auditService
;
@Resource
private
AuditHelper
auditHelper
;
@Resource
private
AuditTemplate
auditTemplate
;
@Override
public
Wrapper
<
Fortune
>
getQueryWrapper
(
FortuneQueryRequest
fortuneQueryRequest
)
{
...
...
@@ -767,6 +778,11 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
return
false
;
}
return
auditTemplate
.
execute
(
"出账管理"
,
1
,
"批量新增出账记录"
,
ctx
->
doAddFortuneBatch
(
fortuneAddRequestList
,
ctx
));
}
private
Boolean
doAddFortuneBatch
(
List
<
FortuneAddRequest
>
fortuneAddRequestList
,
AuditContext
ctx
)
{
Set
<
String
>
policyNoSet
=
fortuneAddRequestList
.
stream
()
.
map
(
FortuneAddRequest:
:
getPolicyNo
)
.
filter
(
StringUtils:
:
isNotBlank
).
collect
(
Collectors
.
toSet
());
...
...
@@ -810,6 +826,8 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
String
realName
=
currentLoginUser
.
getRealName
();
List
<
Fortune
>
fortuneList
=
new
ArrayList
<>();
// 收集自动创建的 ExpectedFortune bizId
List
<
String
>
createdExpectedBizIds
=
new
ArrayList
<>();
for
(
FortuneAddRequest
fortuneAddRequest
:
fortuneAddRequestList
)
{
// 校验参数
...
...
@@ -845,6 +863,8 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
.
update
();
// 关联应付款编号
fortune
.
setPayableNo
(
payableNo
);
// 记录自动创建的 expectedFortune
createdExpectedBizIds
.
add
(
expectedFortune
.
getExpectedFortuneBizId
());
}
else
{
// 如果有预计出账记录,提示去应付款管理页面修改金额,而不是在出账页面新增
throw
new
BusinessException
(
ResultCode
.
FAIL
.
getCode
(),
fortuneAddRequest
.
getFortuneName
()
+
" 已存在应付记录,请在应付款管理页面修改金额"
);
...
...
@@ -888,6 +908,25 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
}
this
.
saveBatch
(
fortuneList
);
// 审计:fortune INSERT
if
(
CollUtil
.
isNotEmpty
(
fortuneList
))
{
Map
<
String
,
Fortune
>
insertMap
=
fortuneList
.
stream
()
.
collect
(
Collectors
.
toMap
(
Fortune:
:
getFortuneBizId
,
Function
.
identity
()));
auditHelper
.
record
(
"fortune"
,
null
,
insertMap
,
ctx
);
}
// 审计:expected_fortune INSERT(自动创建时)
if
(
CollUtil
.
isNotEmpty
(
createdExpectedBizIds
))
{
List
<
ExpectedFortune
>
createdList
=
expectedFortuneService
.
lambdaQuery
()
.
in
(
ExpectedFortune:
:
getExpectedFortuneBizId
,
createdExpectedBizIds
)
.
list
();
if
(
CollUtil
.
isNotEmpty
(
createdList
))
{
Map
<
String
,
ExpectedFortune
>
efInsertMap
=
createdList
.
stream
()
.
collect
(
Collectors
.
toMap
(
ExpectedFortune:
:
getExpectedFortuneBizId
,
Function
.
identity
()));
auditHelper
.
record
(
"expected_fortune"
,
null
,
efInsertMap
,
ctx
);
}
}
return
true
;
}
...
...
yd-csf-service/src/main/resources/mappers/AuditLogDataChangeMapper.xml
0 → 100644
View file @
4bf8eaf1
<?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.yd.csf.service.dao.AuditLogDataChangeMapper"
>
<resultMap
id=
"BaseResultMap"
type=
"com.yd.csf.service.model.SysOperDataChange"
>
<id
property=
"id"
column=
"id"
/>
<result
property=
"requestId"
column=
"request_id"
/>
<result
property=
"operLogId"
column=
"oper_log_id"
/>
<result
property=
"tableName"
column=
"table_name"
/>
<result
property=
"recordId"
column=
"record_id"
/>
<result
property=
"fieldName"
column=
"field_name"
/>
<result
property=
"fieldComment"
column=
"field_comment"
/>
<result
property=
"oldValue"
column=
"old_value"
/>
<result
property=
"newValue"
column=
"new_value"
/>
<result
property=
"changeType"
column=
"change_type"
/>
<result
property=
"createTime"
column=
"create_time"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
id
,request_id,oper_log_id,table_name,record_id,field_name,
field_comment,old_value,new_value,change_type,create_time
</sql>
</mapper>
yd-csf-service/src/main/resources/mappers/AuditLogDataSnapshotMapper.xml
0 → 100644
View file @
4bf8eaf1
<?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.yd.csf.service.dao.AuditLogDataSnapshotMapper"
>
<resultMap
id=
"BaseResultMap"
type=
"com.yd.csf.service.model.SysOperDataSnapshot"
>
<id
property=
"id"
column=
"id"
/>
<result
property=
"requestId"
column=
"request_id"
/>
<result
property=
"tableName"
column=
"table_name"
/>
<result
property=
"recordId"
column=
"record_id"
/>
<result
property=
"beforeJson"
column=
"before_json"
/>
<result
property=
"afterJson"
column=
"after_json"
/>
<result
property=
"createTime"
column=
"create_time"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
id
,request_id,table_name,record_id,before_json,after_json,
create_time
</sql>
</mapper>
yd-csf-service/src/main/resources/mappers/AuditLogMapper.xml
0 → 100644
View file @
4bf8eaf1
<?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.yd.csf.service.dao.AuditLogMapper"
>
<resultMap
id=
"BaseResultMap"
type=
"com.yd.csf.service.model.SysOperLog"
>
<id
property=
"id"
column=
"id"
/>
<result
property=
"requestId"
column=
"request_id"
/>
<result
property=
"module"
column=
"module"
/>
<result
property=
"businessType"
column=
"business_type"
/>
<result
property=
"method"
column=
"method"
/>
<result
property=
"content"
column=
"content"
/>
<result
property=
"businessId"
column=
"business_id"
/>
<result
property=
"operationType"
column=
"operation_type"
/>
<result
property=
"userId"
column=
"user_id"
/>
<result
property=
"operName"
column=
"oper_name"
/>
<result
property=
"deptName"
column=
"dept_name"
/>
<result
property=
"operUrl"
column=
"oper_url"
/>
<result
property=
"operIp"
column=
"oper_ip"
/>
<result
property=
"operLocation"
column=
"oper_location"
/>
<result
property=
"operParam"
column=
"oper_param"
/>
<result
property=
"jsonResult"
column=
"json_result"
/>
<result
property=
"status"
column=
"status"
/>
<result
property=
"errorMsg"
column=
"error_msg"
/>
<result
property=
"operTime"
column=
"oper_time"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
id
,request_id,module,business_type,method,content,
business_id,operation_type,user_id,oper_name,dept_name,
oper_url,oper_ip,oper_location,oper_param,json_result,
status,error_msg,oper_time
</sql>
</mapper>
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