Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
Z
zlmy-cloud
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
zlmy
zlmy-cloud
Commits
ad7f2c82
Commit
ad7f2c82
authored
Nov 28, 2025
by
鲁鸿波
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
所有作业3天未完成的,需要重新发起申请。
危险作业到交底环节后按固定时间判断是否超时,超时自动取消
parent
3954a3b7
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1267 additions
and
12 deletions
+1267
-12
上线说明.md
zlmy-modules/zlmy-boot/doc/国产化/上线说明.md
+59
-0
HazardWorkPlanScheduler.java
.../com/testor/common/scheduler/HazardWorkPlanScheduler.java
+427
-0
DangerousOperationValidator.java
...a/com/testor/common/util/DangerousOperationValidator.java
+68
-4
THazardWorkPlanController.java
...r/module/hazard/controller/THazardWorkPlanController.java
+2
-2
THazardWorkPlanExpiredLogController.java
...azard/controller/THazardWorkPlanExpiredLogController.java
+52
-0
THazardWorkPlanDao.java
...java/com/testor/module/hazard/dao/THazardWorkPlanDao.java
+15
-0
THazardWorkPlanExpiredLogDao.java
...estor/module/hazard/dao/THazardWorkPlanExpiredLogDao.java
+9
-0
THazardWorkPlan.java
...om/testor/module/hazard/model/domain/THazardWorkPlan.java
+18
-0
THazardWorkPlanExpiredLog.java
...module/hazard/model/domain/THazardWorkPlanExpiredLog.java
+106
-0
WorkPlanStatusEnum.java
.../testor/module/hazard/model/enums/WorkPlanStatusEnum.java
+3
-1
THazardWorkPlanExpiredLogService.java
...dule/hazard/service/THazardWorkPlanExpiredLogService.java
+25
-0
THazardWorkPlanService.java
.../testor/module/hazard/service/THazardWorkPlanService.java
+1
-1
THazardWorkPlanExpiredLogServiceImpl.java
...rd/service/impl/THazardWorkPlanExpiredLogServiceImpl.java
+429
-0
THazardWorkPlanServiceImpl.java
...odule/hazard/service/impl/THazardWorkPlanServiceImpl.java
+5
-4
THazardWorkPlan.xml
...boot/src/main/resources/mapper/hazard/THazardWorkPlan.xml
+16
-0
THazardWorkPlanExpiredLogDao.xml
.../resources/mapper/hazard/THazardWorkPlanExpiredLogDao.xml
+32
-0
No files found.
zlmy-modules/zlmy-boot/doc/国产化/上线说明.md
View file @
ad7f2c82
...
@@ -437,3 +437,62 @@ COMMENT ON COLUMN t_train_examination_manage_retake.pass_score IS '及格分数'
...
@@ -437,3 +437,62 @@ COMMENT ON COLUMN t_train_examination_manage_retake.pass_score IS '及格分数'
ALTER TABLE t_hazard_disclosure ADD guardian_signature varchar(255) NULL;
ALTER TABLE t_hazard_disclosure ADD guardian_signature varchar(255) NULL;
COMMENT ON COLUMN t_hazard_disclosure.guardian_signature IS '监护人签字';
COMMENT ON COLUMN t_hazard_disclosure.guardian_signature IS '监护人签字';
#20251205上线需求
ALTER TABLE t_hazard_work_plan ADD hazard_license_pass_time datetime;
COMMENT ON COLUMN t_hazard_work_plan.hazard_license_pass_time IS '安全许可证通过时间';
ALTER TABLE t_hazard_work_plan ADD is_fully_invested varchar(50);
COMMENT ON COLUMN t_hazard_work_plan.is_fully_invested IS '是否满仓(1:是,2:否)';
ALTER TABLE t_hazard_work_plan ADD is_full varchar(50);
COMMENT ON COLUMN t_hazard_work_plan.is_full IS '是否7~9人(1:是,2:否)';
INSERT INTO "t_sys_dict_type" ("dict_id", "dict_name", "dict_type", "is_sys", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids", "tree_sort", "cascaded") VALUES ('1', '危险作业超时检测是否可以执行', 'plan_expired', '1', '0', NULL, '2025-11-28 15:30:11', NULL, '2025-11-28 15:30:11', NULL, NULL, NULL, NULL, '0');
INSERT INTO t_sys_dict_data" ("dict_data_id", "dict_id", "dict_key", "dict_value", "tree_sort", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids") VALUES ('4', '1', '1', '可以执行', '0', '0', NULL, '2025-11-28 15:31:44', NULL, '2025-11-28 15:31:44', NULL, '0', '0,');
添加表t_hazard_work_plan_expired_log
-- public.t_hazard_work_plan_expired_log definition
-- Drop table
-- DROP TABLE public.t_hazard_work_plan_expired_log;
CREATE TABLE public.t_hazard_work_plan_expired_log (
id varchar(64) NOT NULL,
plan_id varchar(64) NULL, -- 作业id
code varchar(30) NULL, -- 作业编码
work_type varchar(50) NULL, -- 作业类型
danger_level varchar(50) NULL, -- 作业级别
expired_reason varchar(200) NULL, -- 超时原因(三天内未完成,安全许可申请审批通过后未在规定时间内完成)
before_expiration varchar(100) NULL, -- 关闭前状态
hazard_license_pass_time sys."datetime" NULL, -- 安全许可申请通过时间
actual_duration_hours numeric(10, 2) NULL, -- 实际持续小时数
plan_create_date sys."timestamp" NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 作业创建时间
status varchar(1) NULL DEFAULT '0'::varchar,
create_by varchar(64) NULL,
create_date "timestamp" NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_by varchar(64) NULL,
update_date "timestamp" NOT NULL DEFAULT CURRENT_TIMESTAMP,
remarks varchar(100) NULL
);
COMMENT ON TABLE public.t_hazard_work_plan_expired_log IS '危险作业-超时自动关闭记录表';
-- Column comments
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.plan_id IS '作业id';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.code IS '作业编码';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.work_type IS '作业类型';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.danger_level IS '作业级别';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.expired_reason IS '超时原因(三天内未完成,安全许可申请审批通过后未在规定时间内完成)';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.before_expiration IS '关闭前状态';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.hazard_license_pass_time IS '安全许可申请通过时间';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.actual_duration_hours IS '实际持续小时数';
COMMENT ON COLUMN public.t_hazard_work_plan_expired_log.plan_create_date IS '作业创建时间';
zlmy-modules/zlmy-boot/src/main/java/com/testor/common/scheduler/HazardWorkPlanScheduler.java
0 → 100644
View file @
ad7f2c82
package
com
.
testor
.
common
.
scheduler
;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
import
com.testor.biz.sys.dict.data.model.domain.SysDictData
;
import
com.testor.module.hazard.dao.THazardWorkPlanDao
;
import
com.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao
;
import
com.testor.module.hazard.model.domain.THazardWorkPlan
;
import
com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog
;
import
com.testor.module.hazard.model.enums.WorkPlanStatusEnum
;
import
com.testor.module.sys.service.NewSysDictDataService
;
import
com.testor.common.util.DangerousOperationValidator
;
import
lombok.extern.slf4j.Slf4j
;
import
org.flowable.engine.HistoryService
;
import
org.flowable.engine.RuntimeService
;
import
org.flowable.engine.runtime.ProcessInstance
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.PostConstruct
;
import
java.math.BigDecimal
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
/**
* HazardWorkPlanScheduler - 优化版(版本 B)
*
* - 字典缓存(可刷新)
* - 统一过期处理流程(日志 -> 停止流程 -> 更新业务状态)
* - 更稳健的 flowable 操作(先查再删,删除历史)
* - 单个 plan 异常捕获,不影响其他计划处理
*
* 注意:
* - 如果你的 DAO 操作需要事务,请在单独需要原子性的私有方法上添加 @Transactional
* - 如果你希望字典立即生效可调用 refreshDictCache()
*/
@Component
@Slf4j
public
class
HazardWorkPlanScheduler
{
private
static
final
String
DICT_ENABLE_ID
=
"1"
;
private
static
final
String
DICT_ENABLE_VALUE
=
"可以执行"
;
// 字典id
private
static
final
String
DICT_WORK_TYPE
=
"42a87414a06a4f57b9d3ffb1907284b4"
;
private
static
final
String
DICT_WORK_LEVEL
=
"222842ea3bb4468bbbeaa3856a4f2731"
;
@Autowired
private
THazardWorkPlanDao
hazardWorkPlanDao
;
@Autowired
private
NewSysDictDataService
dictDataService
;
@Autowired
private
THazardWorkPlanExpiredLogDao
hazardWorkPlanExpiredLogDao
;
@Autowired
private
RuntimeService
runtimeService
;
@Autowired
private
HistoryService
historyService
;
// 缓存:key = dictValue, value = SysDictData
private
final
Map
<
String
,
SysDictData
>
workTypeCache
=
new
ConcurrentHashMap
<>();
private
final
Map
<
String
,
SysDictData
>
workLevelCache
=
new
ConcurrentHashMap
<>();
@PostConstruct
public
void
init
()
{
refreshDictCache
();
}
/**
* 定时刷新字典缓存(每 10 分钟刷新一次,保证字典变更能生效)
*/
@Scheduled
(
cron
=
"0 0/10 * * * ?"
)
public
void
refreshDictCacheScheduled
()
{
refreshDictCache
();
}
private
void
refreshDictCache
()
{
try
{
Map
<
String
,
SysDictData
>
typeMap
=
dictDataService
.
getDictId
(
DICT_WORK_TYPE
)
.
stream
()
.
collect
(
Collectors
.
toMap
(
SysDictData:
:
getDictValue
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
Map
<
String
,
SysDictData
>
levelMap
=
dictDataService
.
getDictId
(
DICT_WORK_LEVEL
)
.
stream
()
.
collect
(
Collectors
.
toMap
(
SysDictData:
:
getDictValue
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
workTypeCache
.
clear
();
workTypeCache
.
putAll
(
typeMap
);
workLevelCache
.
clear
();
workLevelCache
.
putAll
(
levelMap
);
log
.
info
(
"HazardWorkPlanScheduler 字典缓存刷新成功:workType={}, workLevel={}"
,
workTypeCache
.
size
(),
workLevelCache
.
size
());
}
catch
(
Exception
ex
)
{
log
.
error
(
"刷新字典缓存失败"
,
ex
);
}
}
/**
* 每5分钟检查安全许可通过后仍在运行的作业
*/
@Scheduled
(
cron
=
"0 0/5 * * * ?"
)
public
void
refreshSwitch
()
{
if
(!
isSchedulerEnabled
())
{
log
.
debug
(
"refreshSwitch: 调度被禁用(字典值非 {})"
,
DICT_ENABLE_VALUE
);
return
;
}
log
.
info
(
"开始---refreshSwitch----查询所有危险作业已安全许可申请审批通过后未完成的作业"
);
List
<
THazardWorkPlan
>
plans
;
try
{
plans
=
hazardWorkPlanDao
.
selectHazardLicensePassTime
();
}
catch
(
Exception
e
)
{
log
.
error
(
"查询 selectHazardLicensePassTime 失败"
,
e
);
return
;
}
if
(
plans
==
null
||
plans
.
isEmpty
())
{
log
.
info
(
"refreshSwitch: 无需处理的计划"
);
return
;
}
for
(
THazardWorkPlan
plan
:
plans
)
{
try
{
processPlanWithCaches
(
plan
);
}
catch
(
Exception
e
)
{
// 单个 plan 异常不影响其他计划
log
.
error
(
"处理计划异常,planId={}, code={}"
,
plan
==
null
?
null
:
plan
.
getId
(),
plan
==
null
?
null
:
plan
.
getCode
(),
e
);
}
}
log
.
info
(
"结束---refreshSwitch-----查询所有危险作业已安全许可申请审批通过后未完成的作业"
);
}
/**
* 每小时检查所有未完成作业
*/
@Scheduled
(
cron
=
"0 0 * * * ?"
)
public
void
refreshSwitch1
()
{
if
(!
isSchedulerEnabled
())
{
log
.
debug
(
"refreshSwitch1: 调度被禁用(字典值非 {})"
,
DICT_ENABLE_VALUE
);
return
;
}
log
.
info
(
"开始---refreshSwitch1-------查询所有危险作业未完成的作业"
);
List
<
THazardWorkPlan
>
plans
;
try
{
plans
=
hazardWorkPlanDao
.
selectNotCompleteList
();
}
catch
(
Exception
e
)
{
log
.
error
(
"查询 selectNotCompleteList 失败"
,
e
);
return
;
}
if
(
plans
==
null
||
plans
.
isEmpty
())
{
log
.
info
(
"refreshSwitch1: 无需处理的计划"
);
return
;
}
for
(
THazardWorkPlan
plan
:
plans
)
{
try
{
checkThreeDaysExpiredRelaxed
(
plan
);
}
catch
(
Exception
e
)
{
log
.
error
(
"宽松检查处理异常,planId={}, code={}"
,
plan
==
null
?
null
:
plan
.
getId
(),
plan
==
null
?
null
:
plan
.
getCode
(),
e
);
}
}
log
.
info
(
"结束---refreshSwitch1-------查询所有危险作业未完成的作业"
);
}
/****************************
* 核心处理函数
****************************/
private
void
processPlanWithCaches
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
;
}
// 从缓存读取字典,减少 DB 查询
SysDictData
workTypeDict
=
workTypeCache
.
get
(
plan
.
getWorkType
());
SysDictData
workLevelDict
=
workLevelCache
.
get
(
plan
.
getWorkLevel
());
if
(
workTypeDict
==
null
||
workLevelDict
==
null
)
{
log
.
warn
(
"字典缺失,跳过处理 planId={}, workType={}, workLevel={}"
,
plan
.
getId
(),
plan
.
getWorkType
(),
plan
.
getWorkLevel
());
return
;
}
processHazardWorkPlan
(
plan
,
workTypeDict
,
workLevelDict
);
}
public
void
processHazardWorkPlan
(
THazardWorkPlan
plan
,
SysDictData
workTypeDict
,
SysDictData
workLevelDict
)
{
if
(
workTypeDict
==
null
||
workLevelDict
==
null
||
plan
==
null
)
{
return
;
}
String
workTypeName
=
workTypeDict
.
getDictValue
();
String
dangerLevelName
=
workLevelDict
.
getDictValue
();
DangerousOperationValidator
.
OperationType
operationType
=
DangerousOperationValidator
.
OperationType
.
fromDictValue
(
workTypeName
);
DangerousOperationValidator
.
DangerLevel
dangerLevel
=
DangerousOperationValidator
.
DangerLevel
.
fromDictValue
(
dangerLevelName
);
if
(
operationType
==
null
||
dangerLevel
==
null
)
{
log
.
warn
(
"无法识别的作业类型或危险等级: {} - {} for planId={}"
,
workTypeName
,
dangerLevelName
,
plan
.
getId
());
return
;
}
// 计算从审批通过到现在的小时数
double
actualHours
=
calculateHoursBetween
(
plan
.
getHazardLicensePassTime
());
// 验证规则
String
validationResult
=
DangerousOperationValidator
.
validateOperation
(
workTypeName
,
dangerLevelName
,
actualHours
,
plan
);
if
(!
"在安全时间内"
.
equals
(
validationResult
))
{
handleExpiredOperation
(
plan
,
validationResult
,
operationType
,
dangerLevel
,
actualHours
);
}
else
{
log
.
debug
(
"作业在安全时间内, planId={}, hours={}"
,
plan
.
getId
(),
actualHours
);
}
}
/**
* 处理过期(核心步骤:记录日志 -> 停止流程 -> 更新业务状态)
*/
@Transactional
public
void
handleExpiredOperation
(
THazardWorkPlan
plan
,
String
validationResult
,
DangerousOperationValidator
.
OperationType
operationType
,
DangerousOperationValidator
.
DangerLevel
dangerLevel
,
double
actualHours
)
{
log
.
warn
(
"作业过期 - planId={}, code={}, type={}, level={}, hours={}, reason={}"
,
plan
.
getId
(),
plan
.
getCode
(),
operationType
==
null
?
null
:
operationType
.
getName
(),
dangerLevel
==
null
?
null
:
dangerLevel
.
getLevel
(),
actualHours
,
validationResult
);
// 1) 记录过期日志
try
{
THazardWorkPlanExpiredLog
expiredLog
=
new
THazardWorkPlanExpiredLog
();
expiredLog
.
setPlanId
(
plan
.
getId
());
expiredLog
.
setCode
(
plan
.
getCode
());
expiredLog
.
setWorkType
(
operationType
==
null
?
null
:
operationType
.
getName
());
expiredLog
.
setDangerLevel
(
dangerLevel
==
null
?
null
:
dangerLevel
.
getLevel
());
expiredLog
.
setExpiredReason
(
"作业未在安全时间内完成: "
+
validationResult
);
expiredLog
.
setBeforeExpiration
(
plan
.
getStatus
());
expiredLog
.
setHazardLicensePassTime
(
plan
.
getHazardLicensePassTime
());
expiredLog
.
setActualDurationHours
(
BigDecimal
.
valueOf
(
actualHours
));
expiredLog
.
setPlanCreateDate
(
plan
.
getCreateDate
());
expiredLog
.
setCreateBy
(
"system-auto"
);
expiredLog
.
setCreateDate
(
new
Date
());
hazardWorkPlanExpiredLogDao
.
insert
(
expiredLog
);
}
catch
(
Exception
e
)
{
log
.
error
(
"插入过期日志失败,planId={}"
,
plan
.
getId
(),
e
);
}
// 2) 停止 Flowable 流程
stopFlowableProcess
(
plan
);
// 3) 更新业务状态
try
{
updateOperationStatus
(
plan
,
WorkPlanStatusEnum
.
TIMEOUT_CANCELED
.
getValue
());
}
catch
(
Exception
e
)
{
log
.
error
(
"更新作业状态失败,planId={}, code={}"
,
plan
.
getId
(),
plan
.
getCode
(),
e
);
}
}
/**
* 检查3天过期逻辑
*/
private
void
checkThreeDaysExpiredRelaxed
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
;
}
double
hoursSinceCreation
=
calculateHoursBetween
(
plan
.
getHazardLicensePassTime
());
if
(
hoursSinceCreation
>
72
)
{
handleThreeDaysExpired
(
plan
,
hoursSinceCreation
);
}
else
{
log
.
debug
(
"检查通过 - planId={}, hoursSinceCreation={}"
,
plan
.
getId
(),
hoursSinceCreation
);
}
}
private
void
handleThreeDaysExpired
(
THazardWorkPlan
plan
,
double
actualHours
)
{
log
.
warn
(
"3天过期 - planId={}, code={}, hoursSinceCreation={}"
,
plan
.
getId
(),
plan
.
getCode
(),
actualHours
);
// 记录日志
try
{
THazardWorkPlanExpiredLog
expiredLog
=
new
THazardWorkPlanExpiredLog
();
expiredLog
.
setPlanId
(
plan
.
getId
());
expiredLog
.
setCode
(
plan
.
getCode
());
expiredLog
.
setWorkType
(
plan
.
getWorkType
());
expiredLog
.
setDangerLevel
(
plan
.
getWorkLevel
());
expiredLog
.
setExpiredReason
(
"作业创建后3天内未完成,需要重新发起申请"
);
expiredLog
.
setBeforeExpiration
(
plan
.
getWorkStatus
());
expiredLog
.
setHazardLicensePassTime
(
plan
.
getHazardLicensePassTime
());
expiredLog
.
setActualDurationHours
(
BigDecimal
.
valueOf
(
actualHours
));
expiredLog
.
setPlanCreateDate
(
plan
.
getCreateDate
());
expiredLog
.
setStatus
(
"0"
);
expiredLog
.
setCreateBy
(
"system-relaxed"
);
expiredLog
.
setCreateDate
(
new
Date
());
hazardWorkPlanExpiredLogDao
.
insert
(
expiredLog
);
}
catch
(
Exception
e
)
{
log
.
error
(
"记录3天过期日志失败,planId={}"
,
plan
.
getId
(),
e
);
}
// 停止流程并更新状态
stopFlowableProcess
(
plan
);
try
{
// 更新状态
updateOperationStatus
(
plan
,
WorkPlanStatusEnum
.
TIMEOUT_CANCELED
.
getValue
());
}
catch
(
Exception
e
)
{
log
.
error
(
"3天过期后更新作业状态失败,planId={}"
,
plan
.
getId
(),
e
);
}
}
/**
* 检查调度是否启用(通过字典开关)
*/
private
boolean
isSchedulerEnabled
()
{
try
{
List
<
SysDictData
>
dict
=
dictDataService
.
getDictId
(
DICT_ENABLE_ID
);
if
(
dict
!=
null
&&
!
dict
.
isEmpty
())
{
return
DICT_ENABLE_VALUE
.
equals
(
dict
.
get
(
0
).
getDictValue
());
}
}
catch
(
Exception
e
)
{
log
.
error
(
"检查调度开关失败"
,
e
);
}
return
false
;
}
/**
* 计算从 start 到当前的小时数(对 null 做防护)
*/
private
double
calculateHoursBetween
(
Date
start
)
{
if
(
start
==
null
)
{
return
0
d
;
}
long
diffMillis
=
System
.
currentTimeMillis
()
-
start
.
getTime
();
return
diffMillis
/
(
1000.0
*
60
*
60
);
}
/**
* 停止流程(更稳健的实现:先查询流程实例是否存在,再删除运行时并删除历史)
* 内部捕获异常,保证调度器稳定运行。
*
* 注意:如果你希望在删除历史前保留审计,请删除 historyService.deleteHistoricProcessInstance 调用。
*/
private
void
stopFlowableProcess
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
;
}
String
processInstanceId
=
plan
.
getProcessId
();
// 保持你当前字段名
if
(
StringUtils
.
isBlank
(
processInstanceId
))
{
log
.
debug
(
"stopFlowableProcess: processId 为空,跳过,planId={}"
,
plan
.
getId
());
return
;
}
try
{
ProcessInstance
pi
=
runtimeService
.
createProcessInstanceQuery
()
.
processInstanceId
(
processInstanceId
)
.
singleResult
();
if
(
pi
==
null
)
{
log
.
info
(
"流程实例不存在或已结束,跳过删除,processInstanceId={}, planId={}"
,
processInstanceId
,
plan
.
getId
());
// 如果你希望同时清理历史未完成记录,可尝试删除历史(此处不做以免误删)
try
{
// 如果确实需要删除历史:historyService.deleteHistoricProcessInstance(processInstanceId);
}
catch
(
Exception
ex
)
{
log
.
warn
(
"尝试删除历史流程失败,processInstanceId={}"
,
processInstanceId
,
ex
);
}
return
;
}
// 删除运行时流程实例
runtimeService
.
deleteProcessInstance
(
processInstanceId
,
"系统超时自动取消"
);
// 根据业务决定是否删除历史记录;此处删除历史,避免残留(可注释)
try
{
historyService
.
deleteHistoricProcessInstance
(
processInstanceId
);
}
catch
(
Exception
e
)
{
// 删除历史非关键路径:记录日志即可
log
.
warn
(
"删除历史流程实例失败 processInstanceId={}, err={}"
,
processInstanceId
,
e
.
getMessage
());
}
log
.
info
(
"已停止流程实例 processInstanceId={} (planId={})"
,
processInstanceId
,
plan
.
getId
());
}
catch
(
Exception
e
)
{
log
.
error
(
"停止流程失败 processInstanceId={}, planId={}"
,
processInstanceId
,
plan
.
getId
(),
e
);
}
}
/**
* 更新业务作业状态(局部更新,避免覆盖其他字段)
* 如果你希望该更新与过期日志插入为同一事务,请在本方法或调用端加 @Transactional
*/
private
void
updateOperationStatus
(
THazardWorkPlan
plan
,
String
newStatus
)
{
if
(
plan
==
null
)
{
return
;
}
try
{
THazardWorkPlan
update
=
new
THazardWorkPlan
();
update
.
setId
(
plan
.
getId
());
update
.
setWorkStatus
(
newStatus
);
update
.
setUpdateDate
(
new
Date
());
// 假设字段名为 updateDate;如果不同请改为你项目字段
hazardWorkPlanDao
.
updateById
(
update
);
log
.
info
(
"更新作业状态成功 planId={}, newStatus={}"
,
plan
.
getId
(),
newStatus
);
}
catch
(
Exception
e
)
{
log
.
error
(
"更新作业状态失败 planId={}, newStatus={}"
,
plan
.
getId
(),
newStatus
,
e
);
throw
e
;
}
}
}
zlmy-modules/zlmy-boot/src/main/java/com/testor/common/util/DangerousOperationValidator.java
View file @
ad7f2c82
package
com
.
testor
.
common
.
util
;
package
com
.
testor
.
common
.
util
;
import
com.testor.module.hazard.model.domain.THazardWorkPlan
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -14,7 +16,8 @@ public class DangerousOperationValidator {
...
@@ -14,7 +16,8 @@ public class DangerousOperationValidator {
IN_WAREHOUSE
(
"进仓作业"
),
IN_WAREHOUSE
(
"进仓作业"
),
OUT_WAREHOUSE
(
"出仓作业"
),
OUT_WAREHOUSE
(
"出仓作业"
),
FLAG_WAREHOUSE
(
"平仓作业"
),
FLAG_WAREHOUSE
(
"平仓作业"
),
IN_OUT_WAREHOUSE
(
"进出仓作业"
);
IN_OUT_WAREHOUSE
(
"进出仓作业"
),
CIRCULATION_FUMIGATION
(
"环流熏蒸作业"
);
private
final
String
name
;
private
final
String
name
;
OperationType
(
String
name
)
{
OperationType
(
String
name
)
{
...
@@ -93,6 +96,12 @@ public class DangerousOperationValidator {
...
@@ -93,6 +96,12 @@ public class DangerousOperationValidator {
// 其他等级不设置限制
// 其他等级不设置限制
TIME_LIMITS
.
put
(
OperationType
.
FUMIGATION
,
fumigationMap
);
TIME_LIMITS
.
put
(
OperationType
.
FUMIGATION
,
fumigationMap
);
// 环流熏蒸
Map
<
DangerLevel
,
Integer
>
circulationFumigationMap
=
new
HashMap
<>();
circulationFumigationMap
.
put
(
DangerLevel
.
HIGH
,
7
*
24
);
// 其他等级不设置限制
TIME_LIMITS
.
put
(
OperationType
.
CIRCULATION_FUMIGATION
,
circulationFumigationMap
);
// 进仓
// 进仓
Map
<
DangerLevel
,
Integer
>
inWarehouseMap
=
new
HashMap
<>();
Map
<
DangerLevel
,
Integer
>
inWarehouseMap
=
new
HashMap
<>();
inWarehouseMap
.
put
(
DangerLevel
.
HIGH
,
12
);
inWarehouseMap
.
put
(
DangerLevel
.
HIGH
,
12
);
...
@@ -122,7 +131,7 @@ public class DangerousOperationValidator {
...
@@ -122,7 +131,7 @@ public class DangerousOperationValidator {
TIME_LIMITS
.
put
(
OperationType
.
IN_OUT_WAREHOUSE
,
inOutWarehouseMap
);
TIME_LIMITS
.
put
(
OperationType
.
IN_OUT_WAREHOUSE
,
inOutWarehouseMap
);
}
}
public
static
String
validateOperation
(
String
workTypeDictValue
,
String
workLevelDictValue
,
double
actualHours
)
{
public
static
String
validateOperation
(
String
workTypeDictValue
,
String
workLevelDictValue
,
double
actualHours
,
THazardWorkPlan
plan
)
{
// 转换为枚举类型
// 转换为枚举类型
OperationType
type
=
OperationType
.
fromDictValue
(
workTypeDictValue
);
OperationType
type
=
OperationType
.
fromDictValue
(
workTypeDictValue
);
DangerLevel
level
=
DangerLevel
.
fromDictValue
(
workLevelDictValue
);
DangerLevel
level
=
DangerLevel
.
fromDictValue
(
workLevelDictValue
);
...
@@ -138,8 +147,8 @@ public class DangerousOperationValidator {
...
@@ -138,8 +147,8 @@ public class DangerousOperationValidator {
return
"在安全时间内"
;
return
"在安全时间内"
;
}
}
//
获取具体等级的时间限制
//
特殊处理:进出仓、进仓、出仓作业的较大危险级别
Integer
timeLimit
=
levelMap
.
get
(
level
);
Integer
timeLimit
=
getAdjustedTimeLimit
(
type
,
level
,
plan
);
// 如果没有找到该等级的限制,返回安全
// 如果没有找到该等级的限制,返回安全
if
(
timeLimit
==
null
)
{
if
(
timeLimit
==
null
)
{
...
@@ -156,4 +165,59 @@ public class DangerousOperationValidator {
...
@@ -156,4 +165,59 @@ public class DangerousOperationValidator {
return
"在安全时间内"
;
return
"在安全时间内"
;
}
}
/**
* 获取调整后的时间限制(处理特殊情况)
*/
private
static
Integer
getAdjustedTimeLimit
(
OperationType
type
,
DangerLevel
level
,
THazardWorkPlan
plan
)
{
// 获取默认的时间限制
Map
<
DangerLevel
,
Integer
>
levelMap
=
TIME_LIMITS
.
get
(
type
);
if
(
levelMap
==
null
)
{
return
null
;
}
Integer
timeLimit
=
levelMap
.
get
(
level
);
if
(
timeLimit
==
null
)
{
return
null
;
}
//如果是非北良的熏蒸作业高度为1小时,如果是北良的为7天
if
(
level
==
DangerLevel
.
HIGH
){
}
// 特殊规则:进出仓、进仓、出仓作业的较大危险级别
if
(
level
==
DangerLevel
.
MEDIUM
&&
(
type
==
OperationType
.
IN_OUT_WAREHOUSE
||
type
==
OperationType
.
IN_WAREHOUSE
||
type
==
OperationType
.
OUT_WAREHOUSE
||
type
==
OperationType
.
FLAG_WAREHOUSE
))
{
// 检查是否满足特殊条件:isFullyInvested为1或者isFull为1
boolean
isSpecialCondition
=
isSpecialConditionMet
(
plan
);
if
(
isSpecialCondition
)
{
// 满足条件:时间限制为24小时
timeLimit
=
24
;
}
else
{
// 不满足条件:时间限制为72小时
timeLimit
=
72
;
}
}
return
timeLimit
;
}
/**
* 检查是否满足特殊条件:isFullyInvested为1或者isFull为1
*/
private
static
boolean
isSpecialConditionMet
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
false
;
}
String
isEscalated
=
plan
.
getIsEscalated
();
String
isFull
=
plan
.
getIsFull
();
return
"1"
.
equals
(
isEscalated
)
||
"1"
.
equals
(
isFull
);
}
}
}
\ No newline at end of file
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/controller/THazardWorkPlanController.java
View file @
ad7f2c82
...
@@ -306,7 +306,7 @@ public class THazardWorkPlanController extends SuperController
...
@@ -306,7 +306,7 @@ public class THazardWorkPlanController extends SuperController
}
}
}
}
@ApiOperation
(
value
=
"危险作业计划时间是否合规"
,
notes
=
"危险作业计划时间是否合规"
)
/*
@ApiOperation(value = "危险作业计划时间是否合规", notes = "危险作业计划时间是否合规")
@GetMapping(value = "/validateOperation")
@GetMapping(value = "/validateOperation")
public BaseResponse validateOperation(String workType, String workLevel, String scheduledStartTime,String scheduledEndTime) throws BusinessException {
public BaseResponse validateOperation(String workType, String workLevel, String scheduledStartTime,String scheduledEndTime) throws BusinessException {
BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
...
@@ -314,7 +314,7 @@ public class THazardWorkPlanController extends SuperController
...
@@ -314,7 +314,7 @@ public class THazardWorkPlanController extends SuperController
baseResponse.setMsg(result);
baseResponse.setMsg(result);
return baseResponse;
return baseResponse;
}
}
*/
@ApiOperation
(
value
=
"任务转签"
,
notes
=
"任务转签"
)
@ApiOperation
(
value
=
"任务转签"
,
notes
=
"任务转签"
)
@GetMapping
(
value
=
"/transferTask"
)
@GetMapping
(
value
=
"/transferTask"
)
...
...
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/controller/THazardWorkPlanExpiredLogController.java
0 → 100644
View file @
ad7f2c82
package
com
.
testor
.
module
.
hazard
.
controller
;
import
com.testor.module.hazard.model.domain.THazardWorkPlan
;
import
com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog
;
import
com.testor.module.hazard.service.THazardWorkPlanExpiredLogService
;
import
com.tongtech.tfw.backend.common.biz.models.BaseResponse
;
import
com.tongtech.tfw.backend.core.helper.ObjectHelper
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
@RestController
@RequestMapping
(
"/hazard/expiredLog"
)
@Api
(
value
=
"THazardWorkPlanExpiredLog"
,
tags
=
"危险作业计划过期日志"
)
@Slf4j
public
class
THazardWorkPlanExpiredLogController
{
@Autowired
private
THazardWorkPlanExpiredLogService
hazardWorkPlanExpiredLogService
;
@ApiOperation
(
value
=
"危险作业计划自动过期"
,
notes
=
"危险作业计划自动过期"
)
@GetMapping
(
value
=
"/refreshSwitch"
)
public
BaseResponse
refreshSwitch
()
{
BaseResponse
baseResponse
=
new
BaseResponse
<>();
hazardWorkPlanExpiredLogService
.
refreshSwitch
();
baseResponse
.
setData
(
true
);
baseResponse
.
setMsg
(
"操作成功"
);
return
baseResponse
;
}
@ApiOperation
(
value
=
"危险作业三天内未完成自动过期"
,
notes
=
"危险作业三天内未完成自动过期"
)
@GetMapping
(
value
=
"/refreshSwitch1"
)
public
BaseResponse
refreshSwitch1
()
{
BaseResponse
baseResponse
=
new
BaseResponse
<>();
hazardWorkPlanExpiredLogService
.
refreshSwitch1
();
baseResponse
.
setData
(
true
);
baseResponse
.
setMsg
(
"操作成功"
);
return
baseResponse
;
}
@ApiOperation
(
value
=
"根据计划id查询过期日志"
,
notes
=
"根据计划id查询过期日志"
)
@GetMapping
(
value
=
"/selectByPlanId"
)
public
BaseResponse
<
THazardWorkPlanExpiredLog
>
selectByPlanId
(
@RequestParam
String
planId
)
{
BaseResponse
<
THazardWorkPlanExpiredLog
>
baseResponse
=
new
BaseResponse
<>();
THazardWorkPlanExpiredLog
hazardWorkPlanExpiredLog
=
hazardWorkPlanExpiredLogService
.
selectByPlanId
(
planId
);
baseResponse
.
setData
(
hazardWorkPlanExpiredLog
);
return
baseResponse
;
}
}
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/dao/THazardWorkPlanDao.java
View file @
ad7f2c82
...
@@ -10,6 +10,8 @@ import org.apache.ibatis.annotations.Param;
...
@@ -10,6 +10,8 @@ import org.apache.ibatis.annotations.Param;
import
org.apache.ibatis.annotations.Select
;
import
org.apache.ibatis.annotations.Select
;
import
org.apache.ibatis.annotations.Update
;
import
org.apache.ibatis.annotations.Update
;
import
java.util.List
;
/**
/**
* 危险作业计划Mapper接口
* 危险作业计划Mapper接口
*
*
...
@@ -29,4 +31,17 @@ public interface THazardWorkPlanDao extends SuperDao<THazardWorkPlan>
...
@@ -29,4 +31,17 @@ public interface THazardWorkPlanDao extends SuperDao<THazardWorkPlan>
@Select
(
"SELECT * FROM t_hazard_work_plan WHERE code = #{code} and status = 0"
)
@Select
(
"SELECT * FROM t_hazard_work_plan WHERE code = #{code} and status = 0"
)
THazardWorkPlan
selectByCode
(
@Param
(
"code"
)
String
code
);
THazardWorkPlan
selectByCode
(
@Param
(
"code"
)
String
code
);
/**
* 查询所有危险作业已安全许可申请审批通过后未完成的作业
* @return
*/
List
<
THazardWorkPlan
>
selectHazardLicensePassTime
();
/**
* 查询所有危险作业未完成的作业
* @return
*/
List
<
THazardWorkPlan
>
selectNotCompleteList
();
}
}
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/dao/THazardWorkPlanExpiredLogDao.java
0 → 100644
View file @
ad7f2c82
package
com
.
testor
.
module
.
hazard
.
dao
;
import
com.testor.module.hazard.model.domain.THazardWorkPlan
;
import
com.tongtech.tfw.backend.common.models.supers.SuperDao
;
import
com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog
;
public
interface
THazardWorkPlanExpiredLogDao
extends
SuperDao
<
THazardWorkPlanExpiredLog
>{
}
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/model/domain/THazardWorkPlan.java
View file @
ad7f2c82
...
@@ -309,6 +309,24 @@ public class THazardWorkPlan extends SuperModel
...
@@ -309,6 +309,24 @@ public class THazardWorkPlan extends SuperModel
@TableField
(
"guardian_signature"
)
@TableField
(
"guardian_signature"
)
private
String
guardianSignature
;
private
String
guardianSignature
;
@ApiModelProperty
(
value
=
"安全许可证通过时间"
)
@TableField
(
"hazard_license_pass_time"
)
private
Date
hazardLicensePassTime
;
/**
* 是否满仓(1:是,2:否)
*/
@ApiModelProperty
(
value
=
"是否满仓(1:是,2:否)"
)
@TableField
(
"is_fully_invested"
)
private
String
isFullyInvested
;
/**
* 是否7~9人(1:是,2:否)
*/
@ApiModelProperty
(
value
=
"是否7~9人(1:是,2:否)"
)
@TableField
(
"is_full"
)
private
String
isFull
;
@ApiModelProperty
(
value
=
"当前流程环节"
)
@ApiModelProperty
(
value
=
"当前流程环节"
)
@TableField
(
exist
=
false
)
@TableField
(
exist
=
false
)
private
String
currentTaskName
;
private
String
currentTaskName
;
...
...
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/model/domain/THazardWorkPlanExpiredLog.java
0 → 100644
View file @
ad7f2c82
package
com
.
testor
.
module
.
hazard
.
model
.
domain
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
lombok.experimental.SuperBuilder
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.tongtech.tfw.backend.common.models.supers.SuperModel
;
import
org.springframework.format.annotation.DateTimeFormat
;
/**
* 危险作业-超时自动关闭记录表对象 t_hazard_work_plan_expired_log
*
* @author testor-framework
* @date 2025-01-XX
*/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
@Accessors
(
chain
=
true
)
@TableName
(
"t_hazard_work_plan_expired_log"
)
@ApiModel
(
value
=
"THazardWorkPlanExpiredLog对象"
,
description
=
"危险作业-超时自动关闭记录表"
)
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public
class
THazardWorkPlanExpiredLog
extends
SuperModel
{
private
static
final
long
serialVersionUID
=
1L
;
/** id */
@ApiModelProperty
(
value
=
"id"
)
@TableId
(
"id"
)
private
String
id
;
/** 作业id */
@ApiModelProperty
(
value
=
"作业id"
)
@TableField
(
"plan_id"
)
private
String
planId
;
/** 作业编码 */
@ApiModelProperty
(
value
=
"作业编码"
)
@TableField
(
"code"
)
private
String
code
;
/** 作业类型 */
@ApiModelProperty
(
value
=
"作业类型"
)
@TableField
(
"work_type"
)
private
String
workType
;
/** 危险等级 */
@ApiModelProperty
(
value
=
"危险等级"
)
@TableField
(
"danger_level"
)
private
String
dangerLevel
;
/** 超时原因 */
@ApiModelProperty
(
value
=
"超时原因"
)
@TableField
(
"expired_reason"
)
private
String
expiredReason
;
/** 关闭前状态 */
@ApiModelProperty
(
value
=
"关闭前状态"
)
@TableField
(
"before_expiration"
)
private
String
beforeExpiration
;
/** 安全许可申请通过时间 */
@ApiModelProperty
(
value
=
"安全许可申请通过时间"
)
@TableField
(
"hazard_license_pass_time"
)
@JsonFormat
(
timezone
=
"GMT+8"
,
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
@DateTimeFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
Date
hazardLicensePassTime
;
/** 实际持续小时数 */
@ApiModelProperty
(
value
=
"实际持续小时数"
)
@TableField
(
"actual_duration_hours"
)
private
BigDecimal
actualDurationHours
;
/** 作业创建时间 */
@ApiModelProperty
(
value
=
"作业创建时间"
)
@TableField
(
"plan_create_date"
)
@JsonFormat
(
timezone
=
"GMT+8"
,
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
@DateTimeFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
Date
planCreateDate
;
// 常量定义
public
static
final
String
ID
=
"id"
;
public
static
final
String
PLAN_ID
=
"plan_id"
;
public
static
final
String
CODE
=
"code"
;
public
static
final
String
WORK_TYPE
=
"work_type"
;
public
static
final
String
DANGER_LEVEL
=
"danger_level"
;
public
static
final
String
EXPIRED_REASON
=
"expired_reason"
;
public
static
final
String
BEFORE_EXPIRATION
=
"before_expiration"
;
public
static
final
String
HAZARD_LICENSE_PASS_TIME
=
"hazard_license_pass_time"
;
public
static
final
String
ACTUAL_DURATION_HOURS
=
"actual_duration_hours"
;
public
static
final
String
PLAN_CREATE_DATE
=
"plan_create_date"
;
}
\ No newline at end of file
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/model/enums/WorkPlanStatusEnum.java
View file @
ad7f2c82
...
@@ -62,7 +62,9 @@ public enum WorkPlanStatusEnum {
...
@@ -62,7 +62,9 @@ public enum WorkPlanStatusEnum {
IN_PROGRESS
(
"10"
,
"进行中"
),
IN_PROGRESS
(
"10"
,
"进行中"
),
TO_BE_CLOSED
(
"11"
,
"待安全许可证关闭"
);
TO_BE_CLOSED
(
"11"
,
"待安全许可证关闭"
),
TIMEOUT_CANCELED
(
"12"
,
"已超时自动取消"
);
private
final
String
value
;
// 状态值
private
final
String
value
;
// 状态值
private
final
String
description
;
// 状态描述
private
final
String
description
;
// 状态描述
...
...
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/service/THazardWorkPlanExpiredLogService.java
0 → 100644
View file @
ad7f2c82
package
com
.
testor
.
module
.
hazard
.
service
;
import
com.testor.module.hazard.model.domain.THazardWorkPlan
;
import
com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog
;
import
com.tongtech.tfw.backend.common.models.supers.SuperService
;
public
interface
THazardWorkPlanExpiredLogService
extends
SuperService
<
THazardWorkPlanExpiredLog
>
{
/**
* 危险作业计划自动过期
*/
public
void
refreshSwitch
();
/**
* 危险作业三天内未完成自动过期
*/
public
void
refreshSwitch1
();
/**
* 根据计划id查询过期日志
* @param planId
* @return
*/
public
THazardWorkPlanExpiredLog
selectByPlanId
(
String
planId
);
}
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/service/THazardWorkPlanService.java
View file @
ad7f2c82
...
@@ -100,7 +100,7 @@ public interface THazardWorkPlanService extends SuperService<THazardWorkPlan> {
...
@@ -100,7 +100,7 @@ public interface THazardWorkPlanService extends SuperService<THazardWorkPlan> {
* @param scheduledEndTime 计划结束时间
* @param scheduledEndTime 计划结束时间
* @return
* @return
*/
*/
String
validateOperation
(
String
workType
,
String
workLevel
,
String
scheduledStartTime
,
String
scheduledEndTime
);
//
String validateOperation(String workType, String workLevel, String scheduledStartTime,String scheduledEndTime);
/**
/**
* 任务转签
* 任务转签
...
...
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/service/impl/THazardWorkPlanExpiredLogServiceImpl.java
0 → 100644
View file @
ad7f2c82
package
com
.
testor
.
module
.
hazard
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
import
com.testor.biz.sys.dict.data.model.domain.SysDictData
;
import
com.testor.common.util.DangerousOperationValidator
;
import
com.testor.module.hazard.dao.THazardWorkPlanDao
;
import
com.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao
;
import
com.testor.module.hazard.model.domain.THazardWorkPlan
;
import
com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog
;
import
com.testor.module.hazard.model.enums.WorkPlanStatusEnum
;
import
com.testor.module.hazard.service.THazardWorkPlanExpiredLogService
;
import
com.testor.module.sys.service.NewSysDictDataService
;
import
com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl
;
import
lombok.extern.slf4j.Slf4j
;
import
org.flowable.engine.HistoryService
;
import
org.flowable.engine.RuntimeService
;
import
org.flowable.engine.runtime.ProcessInstance
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.PostConstruct
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
@Slf4j
@Service
public
class
THazardWorkPlanExpiredLogServiceImpl
extends
SuperServiceImpl
<
THazardWorkPlanExpiredLogDao
,
THazardWorkPlanExpiredLog
>
implements
THazardWorkPlanExpiredLogService
{
private
static
final
String
DICT_ENABLE_ID
=
"1"
;
private
static
final
String
DICT_ENABLE_VALUE
=
"可以执行"
;
// 字典id
private
static
final
String
DICT_WORK_TYPE
=
"42a87414a06a4f57b9d3ffb1907284b4"
;
private
static
final
String
DICT_WORK_LEVEL
=
"222842ea3bb4468bbbeaa3856a4f2731"
;
@Autowired
private
THazardWorkPlanDao
hazardWorkPlanDao
;
@Autowired
private
NewSysDictDataService
dictDataService
;
@Autowired
private
THazardWorkPlanExpiredLogDao
hazardWorkPlanExpiredLogDao
;
@Autowired
private
RuntimeService
runtimeService
;
@Autowired
private
HistoryService
historyService
;
// 缓存:key = dictValue, value = SysDictData
private
final
Map
<
String
,
SysDictData
>
workTypeCache
=
new
ConcurrentHashMap
<>();
private
final
Map
<
String
,
SysDictData
>
workLevelCache
=
new
ConcurrentHashMap
<>();
@PostConstruct
public
void
init
()
{
refreshDictCache
();
}
/**
* 定时刷新字典缓存(每 10 分钟刷新一次,保证字典变更能生效)
*/
public
void
refreshDictCacheScheduled
()
{
refreshDictCache
();
}
private
void
refreshDictCache
()
{
try
{
Map
<
String
,
SysDictData
>
typeMap
=
dictDataService
.
getDictId
(
DICT_WORK_TYPE
)
.
stream
()
.
collect
(
Collectors
.
toMap
(
SysDictData:
:
getDictValue
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
Map
<
String
,
SysDictData
>
levelMap
=
dictDataService
.
getDictId
(
DICT_WORK_LEVEL
)
.
stream
()
.
collect
(
Collectors
.
toMap
(
SysDictData:
:
getDictValue
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
workTypeCache
.
clear
();
workTypeCache
.
putAll
(
typeMap
);
workLevelCache
.
clear
();
workLevelCache
.
putAll
(
levelMap
);
log
.
info
(
"HazardWorkPlanScheduler 字典缓存刷新成功:workType={}, workLevel={}"
,
workTypeCache
.
size
(),
workLevelCache
.
size
());
}
catch
(
Exception
ex
)
{
log
.
error
(
"刷新字典缓存失败"
,
ex
);
}
}
/**
* 每5分钟检查安全许可通过后仍在运行的作业
*/
@Override
public
void
refreshSwitch
()
{
if
(!
isSchedulerEnabled
())
{
log
.
debug
(
"refreshSwitch: 调度被禁用(字典值非 {})"
,
DICT_ENABLE_VALUE
);
return
;
}
log
.
info
(
"开始---refreshSwitch----查询所有危险作业已安全许可申请审批通过后未完成的作业"
);
List
<
THazardWorkPlan
>
plans
;
try
{
plans
=
hazardWorkPlanDao
.
selectHazardLicensePassTime
();
}
catch
(
Exception
e
)
{
log
.
error
(
"查询 selectHazardLicensePassTime 失败"
,
e
);
return
;
}
if
(
plans
==
null
||
plans
.
isEmpty
())
{
log
.
info
(
"refreshSwitch: 无需处理的计划"
);
return
;
}
for
(
THazardWorkPlan
plan
:
plans
)
{
try
{
processPlanWithCaches
(
plan
);
}
catch
(
Exception
e
)
{
// 单个 plan 异常不影响其他计划
log
.
error
(
"处理计划异常,planId={}, code={}"
,
plan
==
null
?
null
:
plan
.
getId
(),
plan
==
null
?
null
:
plan
.
getCode
(),
e
);
}
}
log
.
info
(
"结束---refreshSwitch-----查询所有危险作业已安全许可申请审批通过后未完成的作业"
);
}
/**
* 每小时检查所有未完成作业
*/
@Override
public
void
refreshSwitch1
()
{
if
(!
isSchedulerEnabled
())
{
log
.
debug
(
"refreshSwitch1: 调度被禁用(字典值非 {})"
,
DICT_ENABLE_VALUE
);
return
;
}
log
.
info
(
"开始---refreshSwitch1-------查询所有危险作业未完成的作业"
);
List
<
THazardWorkPlan
>
plans
;
try
{
plans
=
hazardWorkPlanDao
.
selectNotCompleteList
();
}
catch
(
Exception
e
)
{
log
.
error
(
"查询 selectNotCompleteList 失败"
,
e
);
return
;
}
if
(
plans
==
null
||
plans
.
isEmpty
())
{
log
.
info
(
"refreshSwitch1: 无需处理的计划"
);
return
;
}
for
(
THazardWorkPlan
plan
:
plans
)
{
try
{
checkThreeDaysExpiredRelaxed
(
plan
);
}
catch
(
Exception
e
)
{
log
.
error
(
"宽松检查处理异常,planId={}, code={}"
,
plan
==
null
?
null
:
plan
.
getId
(),
plan
==
null
?
null
:
plan
.
getCode
(),
e
);
}
}
log
.
info
(
"结束---refreshSwitch1-------查询所有危险作业未完成的作业"
);
}
/****************************
* 核心处理函数
****************************/
private
void
processPlanWithCaches
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
;
}
// 从缓存读取字典,减少 DB 查询
SysDictData
workTypeDict
=
workTypeCache
.
get
(
plan
.
getWorkType
());
SysDictData
workLevelDict
=
workLevelCache
.
get
(
plan
.
getWorkLevel
());
if
(
workTypeDict
==
null
||
workLevelDict
==
null
)
{
log
.
warn
(
"字典缺失,跳过处理 planId={}, workType={}, workLevel={}"
,
plan
.
getId
(),
plan
.
getWorkType
(),
plan
.
getWorkLevel
());
return
;
}
processHazardWorkPlan
(
plan
,
workTypeDict
,
workLevelDict
);
}
public
void
processHazardWorkPlan
(
THazardWorkPlan
plan
,
SysDictData
workTypeDict
,
SysDictData
workLevelDict
)
{
if
(
workTypeDict
==
null
||
workLevelDict
==
null
||
plan
==
null
)
{
return
;
}
String
workTypeName
=
workTypeDict
.
getDictValue
();
String
dangerLevelName
=
workLevelDict
.
getDictValue
();
DangerousOperationValidator
.
OperationType
operationType
=
DangerousOperationValidator
.
OperationType
.
fromDictValue
(
workTypeName
);
DangerousOperationValidator
.
DangerLevel
dangerLevel
=
DangerousOperationValidator
.
DangerLevel
.
fromDictValue
(
dangerLevelName
);
if
(
operationType
==
null
||
dangerLevel
==
null
)
{
log
.
warn
(
"无法识别的作业类型或危险等级: {} - {} for planId={}"
,
workTypeName
,
dangerLevelName
,
plan
.
getId
());
return
;
}
// 计算从审批通过到现在的小时数
double
actualHours
=
calculateHoursBetween
(
plan
.
getHazardLicensePassTime
());
// 验证规则
String
validationResult
=
DangerousOperationValidator
.
validateOperation
(
workTypeName
,
dangerLevelName
,
actualHours
,
plan
);
if
(!
"在安全时间内"
.
equals
(
validationResult
))
{
handleExpiredOperation
(
plan
,
validationResult
,
operationType
,
dangerLevel
,
actualHours
);
}
else
{
log
.
debug
(
"作业在安全时间内, planId={}, hours={}"
,
plan
.
getId
(),
actualHours
);
}
}
/**
* 处理过期(核心步骤:记录日志 -> 停止流程 -> 更新业务状态)
*/
@Transactional
public
void
handleExpiredOperation
(
THazardWorkPlan
plan
,
String
validationResult
,
DangerousOperationValidator
.
OperationType
operationType
,
DangerousOperationValidator
.
DangerLevel
dangerLevel
,
double
actualHours
)
{
log
.
warn
(
"作业过期 - planId={}, code={}, type={}, level={}, hours={}, reason={}"
,
plan
.
getId
(),
plan
.
getCode
(),
operationType
==
null
?
null
:
operationType
.
getName
(),
dangerLevel
==
null
?
null
:
dangerLevel
.
getLevel
(),
actualHours
,
validationResult
);
// 1) 记录过期日志
try
{
THazardWorkPlanExpiredLog
expiredLog
=
new
THazardWorkPlanExpiredLog
();
expiredLog
.
setPlanId
(
plan
.
getId
());
expiredLog
.
setCode
(
plan
.
getCode
());
expiredLog
.
setWorkType
(
operationType
==
null
?
null
:
operationType
.
getName
());
expiredLog
.
setDangerLevel
(
dangerLevel
==
null
?
null
:
dangerLevel
.
getLevel
());
expiredLog
.
setExpiredReason
(
"作业未在安全时间内完成: "
+
validationResult
);
expiredLog
.
setBeforeExpiration
(
plan
.
getStatus
());
expiredLog
.
setHazardLicensePassTime
(
plan
.
getHazardLicensePassTime
());
expiredLog
.
setActualDurationHours
(
BigDecimal
.
valueOf
(
actualHours
));
expiredLog
.
setPlanCreateDate
(
plan
.
getCreateDate
());
expiredLog
.
setCreateBy
(
"system-auto"
);
expiredLog
.
setCreateDate
(
new
Date
());
hazardWorkPlanExpiredLogDao
.
insert
(
expiredLog
);
}
catch
(
Exception
e
)
{
log
.
error
(
"插入过期日志失败,planId={}"
,
plan
.
getId
(),
e
);
}
// 2) 停止 Flowable 流程
stopFlowableProcess
(
plan
);
// 3) 更新业务状态
try
{
updateOperationStatus
(
plan
,
WorkPlanStatusEnum
.
TIMEOUT_CANCELED
.
getValue
());
}
catch
(
Exception
e
)
{
log
.
error
(
"更新作业状态失败,planId={}, code={}"
,
plan
.
getId
(),
plan
.
getCode
(),
e
);
}
}
/**
* 检查3天过期逻辑
*/
private
void
checkThreeDaysExpiredRelaxed
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
;
}
double
hoursSinceCreation
=
calculateHoursBetween
(
plan
.
getCreateDate
());
if
(
hoursSinceCreation
>
72
)
{
handleThreeDaysExpired
(
plan
,
hoursSinceCreation
);
}
else
{
log
.
debug
(
"检查通过 - planId={}, hoursSinceCreation={}"
,
plan
.
getId
(),
hoursSinceCreation
);
}
}
private
void
handleThreeDaysExpired
(
THazardWorkPlan
plan
,
double
actualHours
)
{
log
.
warn
(
"3天过期 - planId={}, code={}, hoursSinceCreation={}"
,
plan
.
getId
(),
plan
.
getCode
(),
actualHours
);
// 记录日志
try
{
THazardWorkPlanExpiredLog
expiredLog
=
new
THazardWorkPlanExpiredLog
();
expiredLog
.
setPlanId
(
plan
.
getId
());
expiredLog
.
setCode
(
plan
.
getCode
());
expiredLog
.
setWorkType
(
plan
.
getWorkType
());
expiredLog
.
setDangerLevel
(
plan
.
getWorkLevel
());
expiredLog
.
setExpiredReason
(
"作业创建后3天内未完成,需要重新发起申请"
);
expiredLog
.
setBeforeExpiration
(
plan
.
getWorkStatus
());
expiredLog
.
setHazardLicensePassTime
(
plan
.
getHazardLicensePassTime
());
expiredLog
.
setActualDurationHours
(
BigDecimal
.
valueOf
(
actualHours
));
expiredLog
.
setPlanCreateDate
(
plan
.
getCreateDate
());
expiredLog
.
setStatus
(
"0"
);
expiredLog
.
setCreateBy
(
"system-relaxed"
);
expiredLog
.
setCreateDate
(
new
Date
());
hazardWorkPlanExpiredLogDao
.
insert
(
expiredLog
);
}
catch
(
Exception
e
)
{
log
.
error
(
"记录3天过期日志失败,planId={}"
,
plan
.
getId
(),
e
);
}
// 停止流程并更新状态
stopFlowableProcess
(
plan
);
try
{
// 更新状态
updateOperationStatus
(
plan
,
WorkPlanStatusEnum
.
TIMEOUT_CANCELED
.
getValue
());
}
catch
(
Exception
e
)
{
log
.
error
(
"3天过期后更新作业状态失败,planId={}"
,
plan
.
getId
(),
e
);
}
}
/**
* 检查调度是否启用(通过字典开关)
*/
private
boolean
isSchedulerEnabled
()
{
try
{
List
<
SysDictData
>
dict
=
dictDataService
.
getDictId
(
DICT_ENABLE_ID
);
if
(
dict
!=
null
&&
!
dict
.
isEmpty
())
{
return
DICT_ENABLE_VALUE
.
equals
(
dict
.
get
(
0
).
getDictValue
());
}
}
catch
(
Exception
e
)
{
log
.
error
(
"检查调度开关失败"
,
e
);
}
return
false
;
}
/**
* 计算从 start 到当前的小时数(对 null 做防护)
*/
private
double
calculateHoursBetween
(
Date
start
)
{
if
(
start
==
null
)
{
return
0
d
;
}
long
diffMillis
=
System
.
currentTimeMillis
()
-
start
.
getTime
();
return
diffMillis
/
(
1000.0
*
60
*
60
);
}
/**
* 停止流程(更稳健的实现:先查询流程实例是否存在,再删除运行时并删除历史)
* 内部捕获异常,保证调度器稳定运行。
*
* 注意:如果你希望在删除历史前保留审计,请删除 historyService.deleteHistoricProcessInstance 调用。
*/
private
void
stopFlowableProcess
(
THazardWorkPlan
plan
)
{
if
(
plan
==
null
)
{
return
;
}
String
processInstanceId
=
plan
.
getProcessId
();
// 保持你当前字段名
if
(
StringUtils
.
isBlank
(
processInstanceId
))
{
log
.
debug
(
"stopFlowableProcess: processId 为空,跳过,planId={}"
,
plan
.
getId
());
return
;
}
try
{
ProcessInstance
pi
=
runtimeService
.
createProcessInstanceQuery
()
.
processInstanceId
(
processInstanceId
)
.
singleResult
();
if
(
pi
==
null
)
{
log
.
info
(
"流程实例不存在或已结束,跳过删除,processInstanceId={}, planId={}"
,
processInstanceId
,
plan
.
getId
());
// 如果你希望同时清理历史未完成记录,可尝试删除历史(此处不做以免误删)
try
{
// 如果确实需要删除历史:historyService.deleteHistoricProcessInstance(processInstanceId);
}
catch
(
Exception
ex
)
{
log
.
warn
(
"尝试删除历史流程失败,processInstanceId={}"
,
processInstanceId
,
ex
);
}
return
;
}
// 删除运行时流程实例
runtimeService
.
deleteProcessInstance
(
processInstanceId
,
"系统超时自动取消"
);
// 根据业务决定是否删除历史记录;此处删除历史,避免残留(可注释)
try
{
historyService
.
deleteHistoricProcessInstance
(
processInstanceId
);
}
catch
(
Exception
e
)
{
// 删除历史非关键路径:记录日志即可
log
.
warn
(
"删除历史流程实例失败 processInstanceId={}, err={}"
,
processInstanceId
,
e
.
getMessage
());
}
log
.
info
(
"已停止流程实例 processInstanceId={} (planId={})"
,
processInstanceId
,
plan
.
getId
());
}
catch
(
Exception
e
)
{
log
.
error
(
"停止流程失败 processInstanceId={}, planId={}"
,
processInstanceId
,
plan
.
getId
(),
e
);
}
}
/**
* 更新业务作业状态(局部更新,避免覆盖其他字段)
* 如果你希望该更新与过期日志插入为同一事务,请在本方法或调用端加 @Transactional
*/
private
void
updateOperationStatus
(
THazardWorkPlan
plan
,
String
newStatus
)
{
if
(
plan
==
null
)
{
return
;
}
try
{
THazardWorkPlan
update
=
new
THazardWorkPlan
();
update
.
setId
(
plan
.
getId
());
update
.
setWorkStatus
(
newStatus
);
update
.
setUpdateDate
(
new
Date
());
// 假设字段名为 updateDate;如果不同请改为你项目字段
hazardWorkPlanDao
.
updateById
(
update
);
log
.
info
(
"更新作业状态成功 planId={}, newStatus={}"
,
plan
.
getId
(),
newStatus
);
}
catch
(
Exception
e
)
{
log
.
error
(
"更新作业状态失败 planId={}, newStatus={}"
,
plan
.
getId
(),
newStatus
,
e
);
throw
e
;
}
}
@Override
public
THazardWorkPlanExpiredLog
selectByPlanId
(
String
planId
)
{
return
hazardWorkPlanExpiredLogDao
.
selectOne
(
new
LambdaQueryWrapper
<
THazardWorkPlanExpiredLog
>()
.
eq
(
THazardWorkPlanExpiredLog:
:
getPlanId
,
planId
));
}
}
zlmy-modules/zlmy-boot/src/main/java/com/testor/module/hazard/service/impl/THazardWorkPlanServiceImpl.java
View file @
ad7f2c82
...
@@ -627,6 +627,7 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
...
@@ -627,6 +627,7 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
THazardWorkPlan
updWorkPlan
=
new
THazardWorkPlan
();
THazardWorkPlan
updWorkPlan
=
new
THazardWorkPlan
();
updWorkPlan
.
setId
(
id
);
updWorkPlan
.
setId
(
id
);
updWorkPlan
.
setHazardLicensePassTime
(
new
Date
());
this
.
updateById
(
updWorkPlan
);
this
.
updateById
(
updWorkPlan
);
}
}
...
@@ -885,9 +886,9 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
...
@@ -885,9 +886,9 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
return
null
;
return
null
;
}
}
@Override
/*
@Override
public String validateOperation(String workType, String workLevel, String scheduledStartTime, String scheduledEndTime) {
public String validateOperation(String workType, String workLevel, String scheduledStartTime, String scheduledEndTime) {
/*中粮/北良规则如下
*/
/*中粮/北良规则如下
动火作业高度危险: 8小时内
动火作业高度危险: 8小时内
动火作业较大危险: 12小时内
动火作业较大危险: 12小时内
动火作业一般危险: 72小时内
动火作业一般危险: 72小时内
...
@@ -899,7 +900,7 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
...
@@ -899,7 +900,7 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
熏蒸作业高度: 7天内
熏蒸作业高度: 7天内
进出仓高度危险作业: 12小时内
进出仓高度危险作业: 12小时内
进出仓较大危险作业: 24小时内
进出仓较大危险作业: 24小时内
进出仓一般危险作业: 72小时内*/
进出仓一般危险作业: 72小时内*/
/*
SysDictData workTypeDictData = sysDictDataService.getDictDataById(workType);
SysDictData workTypeDictData = sysDictDataService.getDictDataById(workType);
SysDictData workLevelDictData = sysDictDataService.getDictDataById(workLevel);
SysDictData workLevelDictData = sysDictDataService.getDictDataById(workLevel);
String result = "在安全时间内";
String result = "在安全时间内";
...
@@ -912,7 +913,7 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
...
@@ -912,7 +913,7 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
);
);
}
}
return result;
return result;
}
}
*/
// 添加时区支持
// 添加时区支持
...
...
zlmy-modules/zlmy-boot/src/main/resources/mapper/hazard/THazardWorkPlan.xml
View file @
ad7f2c82
...
@@ -33,6 +33,9 @@
...
@@ -33,6 +33,9 @@
<id
column=
"cancel_opinion"
property=
"cancelOpinion"
/>
<id
column=
"cancel_opinion"
property=
"cancelOpinion"
/>
<id
column=
"revoke_opinion"
property=
"revokeOpinion"
/>
<id
column=
"revoke_opinion"
property=
"revokeOpinion"
/>
<id
column=
"guardian_signature"
property=
"guardianSignature"
/>
<id
column=
"guardian_signature"
property=
"guardianSignature"
/>
<id
column=
"hazard_license_pass_time"
property=
"hazardLicensePassTime"
/>
<id
column=
"is_fully_invested"
property=
"isFullyInvested"
/>
<id
column=
"is_full"
property=
"isFull"
/>
</resultMap>
</resultMap>
<select
id=
"selectToDoList"
resultType=
"com.tongtech.tfw.workflow.apis.task.model.dto.TodoTask"
>
<select
id=
"selectToDoList"
resultType=
"com.tongtech.tfw.workflow.apis.task.model.dto.TodoTask"
>
SELECT DISTINCT
SELECT DISTINCT
...
@@ -79,4 +82,17 @@
...
@@ -79,4 +82,17 @@
</if>
</if>
ORDER BY task.CREATE_TIME_ desc
ORDER BY task.CREATE_TIME_ desc
</select>
</select>
<select
id=
"selectHazardLicensePassTime"
resultType=
"com.testor.module.hazard.model.domain.THazardWorkPlan"
>
select * from t_hazard_work_plan
where status ='0' and hazard_license_pass_time is not null
and work_status in('4','8','9','10')
</select>
<select
id=
"selectNotCompleteList"
resultType=
"com.testor.module.hazard.model.domain.THazardWorkPlan"
>
select * from t_hazard_work_plan
where status ='0'
and work_status not in('0','5','6','12')
</select>
</mapper>
</mapper>
\ No newline at end of file
zlmy-modules/zlmy-boot/src/main/resources/mapper/hazard/THazardWorkPlanExpiredLogDao.xml
0 → 100644
View file @
ad7f2c82
<?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.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao"
>
<!-- 通用查询映射结果 -->
<resultMap
id=
"BaseResultMap"
type=
"com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog"
>
<id
column=
"id"
property=
"id"
/>
<result
column=
"plan_id"
property=
"planId"
/>
<result
column=
"code"
property=
"code"
/>
<result
column=
"work_type"
property=
"workType"
/>
<result
column=
"danger_level"
property=
"dangerLevel"
/>
<result
column=
"expired_reason"
property=
"expiredReason"
/>
<result
column=
"before_expiration"
property=
"beforeExpiration"
/>
<result
column=
"hazard_license_pass_time"
property=
"hazardLicensePassTime"
/>
<result
column=
"actual_duration_hours"
property=
"actualDurationHours"
/>
<result
column=
"plan_create_date"
property=
"planCreateDate"
/>
<!-- SuperModel 的字段 -->
<result
column=
"status"
property=
"status"
/>
<result
column=
"create_by"
property=
"createBy"
/>
<result
column=
"create_date"
property=
"createDate"
/>
<result
column=
"update_by"
property=
"updateBy"
/>
<result
column=
"update_date"
property=
"updateDate"
/>
</resultMap>
<!-- 通用查询结果列 -->
<sql
id=
"Base_Column_List"
>
id, plan_id, code, work_type, danger_level, expired_reason, before_expiration,
hazard_license_pass_time, actual_duration_hours, allowed_duration_hours,
plan_create_date, expired_time, remark, status, create_by, create_date, update_by, update_date
</sql>
</mapper>
\ No newline at end of file
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