Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
problem_rectification
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
David Yang
problem_rectification
Commits
3917767f
Commit
3917767f
authored
Jul 29, 2026
by
David Yang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 问题整改转发
parent
9b9085cc
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
165 additions
and
47 deletions
+165
-47
manifest.json
public/manifest.json
+1
-1
app.js
src/app.js
+13
-0
index.jsx
src/components/record-workbench/index.jsx
+1
-0
useSubjectRecord.js
src/pages/RecordDetailDrawer/hooks/useSubjectRecord.js
+7
-2
index.jsx
src/pages/RecordDetailDrawer/index.jsx
+13
-2
Layout.jsx
src/pages/problem_rectification/Layout.jsx
+1
-1
index.jsx
src/pages/problem_rectification/dashboard/index.jsx
+13
-12
index.jsx
src/pages/problem_rectification/flow-table/index.jsx
+0
-0
index.jsx
src/pages/problem_rectification/form/index.jsx
+39
-11
index.jsx
src/pages/problem_rectification/list/index.jsx
+0
-0
problem-rectification.business-flow.md
...blem_rectification/problem-rectification.business-flow.md
+0
-0
problemRectificationDashboardService.js
...lem_rectification/problemRectificationDashboardService.js
+9
-15
problemRectificationFormService.js
.../problem_rectification/problemRectificationFormService.js
+28
-0
problemRectificationListService.js
.../problem_rectification/problemRectificationListService.js
+0
-0
subjectsDefinition.md
src/services/subjectsDefinition.md
+40
-3
No files found.
public/manifest.json
View file @
3917767f
{
"name"
:
"problem_rectification_new"
,
"version"
:
"1.0.
4
"
,
"version"
:
"1.0.
6
"
,
"build"
:
"abc"
,
"description"
:
"merge master"
,
"date"
:
"2025-07-14 19:27:20"
,
...
...
src/app.js
View file @
3917767f
...
...
@@ -2,6 +2,19 @@ import '@/global.less';
import
'@/tailwind.css'
;
import
{
defineApp
}
from
'umi'
;
const
LEGACY_FLOW_PATH
=
'/self_inspection_form'
;
const
appBasePath
=
String
(
PROBLEM_RECTIFICATION_APP_BASE_PATH
||
'/'
).
replace
(
/
\/
+$/
,
''
);
const
legacyFlowPaths
=
new
Set
([
LEGACY_FLOW_PATH
,
`
${
appBasePath
}${
LEGACY_FLOW_PATH
}
`
,
]);
if
(
typeof
window
!==
'undefined'
&&
legacyFlowPaths
.
has
(
window
.
location
.
pathname
))
{
window
.
location
.
replace
(
`
${
appBasePath
}
/problem_rectification_flow_table
${
window
.
location
.
search
}${
window
.
location
.
hash
}
`
,
);
}
export
async
function
getInitialState
()
{
return
{
name
:
'project_manager_xy'
,
...
...
src/components/record-workbench/index.jsx
View file @
3917767f
...
...
@@ -737,6 +737,7 @@ export default function RecordWorkbench({
</
Select
>
)
:
(
<
Input
type=
{
field
.
type
===
'month'
?
'month'
:
'text'
}
value=
{
filters
[
field
.
key
]
||
''
}
onChange=
{
(
event
)
=>
onFiltersChange
?.(
field
.
key
,
event
.
target
.
value
)
}
placeholder=
{
field
.
placeholder
}
...
...
src/pages/RecordDetailDrawer/hooks/useSubjectRecord.js
View file @
3917767f
...
...
@@ -102,7 +102,7 @@ export function useSubjectRecord(recordName, refreshKey, readonly, subjectName)
},
[
recordName
,
refreshKey
,
subjectName
]);
const
handleFieldUpdate
=
async
(
fieldPath
,
newValue
,
fieldDef
)
=>
{
if
(
readonly
||
!
editableRecord
)
{
if
(
readonly
||
remoteRecord
?.
metadata
?.
is_locked
===
true
||
!
editableRecord
)
{
return
;
}
...
...
@@ -122,7 +122,12 @@ export function useSubjectRecord(recordName, refreshKey, readonly, subjectName)
};
const
isFieldDisabled
=
(
fieldPath
,
currentView
)
=>
{
return
isFieldDisabledByView
(
fieldPath
,
currentView
);
return
(
fieldPath
===
'is_locked'
||
fieldPath
===
'metadata.is_locked'
||
remoteRecord
?.
metadata
?.
is_locked
===
true
||
isFieldDisabledByView
(
fieldPath
,
currentView
)
);
};
return
{
...
...
src/pages/RecordDetailDrawer/index.jsx
View file @
3917767f
...
...
@@ -124,6 +124,8 @@ const RecordDetailDrawer = (props, ref) => {
);
const
activeView
=
detailViews
.
find
((
view
)
=>
view
.
name
===
activeTabKey
)
||
detailViews
[
0
];
const
isRecordLocked
=
remoteRecord
?.
metadata
?.
is_locked
===
true
;
const
effectiveReadonly
=
readonly
||
isRecordLocked
;
const
drawerWidth
=
isFullscreen
?
'100vw'
:
typeof
width
===
'number'
?
`
${
width
}
px`
:
width
;
const
disabledFieldSet
=
useMemo
(
()
=>
...
...
@@ -214,22 +216,31 @@ const RecordDetailDrawer = (props, ref) => {
{
error
}
</
div
>
)
:
(
<
div
className=
"space-y-4"
>
{
isRecordLocked
?
(
<
div
className=
"rounded-2xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800"
>
当前问题整改记录已锁定,仅可查看。如需修改,请先在问题清单中解锁。
</
div
>
)
:
null
}
<
SubjectViewContent
view=
{
activeView
}
subject=
{
subject
}
editableRecord=
{
editableRecord
}
onFieldUpdate=
{
handleFieldUpdate
}
onDataChange=
{
onDataChange
}
readonly=
{
r
eadonly
}
readonly=
{
effectiveR
eadonly
}
isFieldDisabled=
{
isDrawerFieldDisabled
}
/>
</
div
>
)
}
</
main
>
<
footer
className=
"border-t border-white/70 bg-white/82 px-6 py-4 backdrop-blur"
>
<
div
className=
"flex items-center justify-between gap-3"
>
<
div
className=
"text-sm text-zinc-500"
>
长文本、附件和状态类字段支持在详情面板内直接维护
{
isRecordLocked
?
'当前记录已锁定,所有业务字段均为只读'
:
'长文本、附件和状态类字段支持在详情面板内直接维护'
}
</
div
>
<
Button
outline
onClick=
{
closeDrawer
}
>
关闭
...
...
src/pages/problem_rectification/Layout.jsx
View file @
3917767f
...
...
@@ -27,7 +27,7 @@ const menuGroups = [
icon
:
HomeModernIcon
,
},
{
name
:
'
业务驾驶舱
'
,
name
:
'
整改分析
'
,
path
:
'/integrity_risk_table/business_dashboard'
,
icon
:
ChartPieIcon
,
},
...
...
src/pages/problem_rectification/dashboard/index.jsx
View file @
3917767f
...
...
@@ -711,10 +711,11 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
?
summary
.
focusIssueGroups
?.[
activeFocusIssueType
.
key
]
||
[]
:
[];
const
isBusinessDashboard
=
dashboardMode
===
'business'
;
const
dashboardTitle
=
isBusinessDashboard
?
'业务驾驶舱'
:
'问题整改驾驶舱'
;
const
dashboardEyebrow
=
isBusinessDashboard
?
'Rectification Analysis'
:
'Leadership Dashboard'
;
const
dashboardTitle
=
isBusinessDashboard
?
'问题整改分析'
:
'问题整改驾驶舱'
;
const
dashboardSubtitle
=
isBusinessDashboard
?
'围绕问题风险定位、部门责任追踪和整改质效评估,
沉淀
业务分析与督办依据。'
:
'
围绕整改完成进度、问题风险定位、部门责任压实和整改质效评估,统一展示今年问题
整改全景。'
;
?
'围绕问题风险定位、部门责任追踪和整改质效评估,
形成
业务分析与督办依据。'
:
'
面向管理层集中展示问题总量、整改进度、闭环情况和逾期风险,快速掌握
整改全景。'
;
const
yearLabel
=
activeYear
===
'all'
?
'全部年份'
:
`${activeYear} 年`
;
return
(
...
...
@@ -725,7 +726,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
<
div
className=
"relative flex flex-wrap items-end justify-between gap-6"
>
<
div
className=
"max-w-4xl"
>
<
div
className=
"text-xs font-semibold uppercase tracking-[0.28em] text-white/75"
>
Integrity Risk Dashboard
{
dashboardEyebrow
}
</
div
>
<
h1
className=
"mt-3 text-3xl font-semibold tracking-tight md:text-[2.55rem]"
>
{
dashboardTitle
}
...
...
@@ -809,6 +810,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
{
!
loading
&&
!
dashboardData
.
isEmpty
&&
!
activeScope
.
isEmpty
?
(
<>
{
!
isBusinessDashboard
?
(
<>
<
section
className=
"space-y-5"
>
<
SectionHeading
eyebrow=
"Overview"
...
...
@@ -848,17 +850,13 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
/>
</
div
>
</
section
>
)
:
null
}
{
isBusinessDashboard
?
(
<>
<
section
className=
"space-y-5"
>
<
SectionHeading
eyebrow=
"Progress"
title=
"整改进度"
description=
"按整改进度统计分布与口径,
辅助判断当前积压状态和督办入口
。"
description=
"按整改进度统计分布与口径,
帮助管理层判断当前积压状态和重点督办方向
。"
/>
<
div
className=
"grid gap-6"
>
<
Panel
title=
"整改进度分布"
description=
"按整改进度统计数量与占比,直观看当前积压主要落在哪个状态。"
...
...
@@ -869,9 +867,12 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
<
EmptyBlock
title=
"暂无整改进度分布数据"
/>
)
}
</
Panel
>
</
div
>
</
section
>
</>
)
:
null
}
{
isBusinessDashboard
?
(
<>
<
section
className=
"space-y-5"
>
<
SectionHeading
eyebrow=
"Risk"
...
...
@@ -997,11 +998,11 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
<
SectionHeading
eyebrow=
"Quality"
title=
"审计整改质效"
description=
"
驾驶舱
只展示综合整改质效结果,具体评估维度在维护页补录和校验。"
description=
"
分析页
只展示综合整改质效结果,具体评估维度在维护页补录和校验。"
/>
<
Panel
title=
"综合整改质效结果"
description=
"按
高、中、低展示最终整改质效等级;暂按“两个及以上高为高、出现低则低、一个高则中”的初步规则计算,具体维度和规则后续确认
。"
description=
"按
六项整改评估字段自动计算并展示高、中、低分布;任一负向维度为低,至少两个正向维度为高,其余有效结果为中
。"
>
{
summary
.
qualityRatingDistribution
.
length
>
0
?
(
<
ReactECharts
option=
{
qualityRatingOption
}
style=
{
{
height
:
380
}
}
/>
...
...
src/pages/problem_rectification/flow-table/index.jsx
View file @
3917767f
This diff is collapsed.
Click to expand it.
src/pages/problem_rectification/form/index.jsx
View file @
3917767f
...
...
@@ -15,10 +15,11 @@ import {
TableRow
,
}
from
'@/catalyst-ui-kit/javascript/table'
;
import
TailwindEditableField
from
'@/pages/RecordDetailDrawer/components/TailwindEditableField'
;
import
{
updateRecord
}
from
'@/services/DataService'
;
import
{
loadRecord
,
updateRecord
}
from
'@/services/DataService'
;
import
{
normalizeText
}
from
'@/utils/subjectView'
;
import
clsx
from
'clsx'
;
import
dayjs
from
'dayjs'
;
import
{
LockClosedIcon
}
from
'@heroicons/react/24/outline'
;
import
{
useContext
,
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
useSearchParams
}
from
'umi'
;
import
{
UserContext
}
from
'@/wrapper/Auth'
;
...
...
@@ -180,6 +181,7 @@ export default function ProblemRectificationFormPage() {
const
currentStep
=
flowData
?.
currentStep
||
'editor'
;
const
viewerRole
=
flowData
?.
viewerRole
||
'guest'
;
const
canEditRecords
=
Boolean
(
flowData
?.
canEditRecords
);
const
hasLockedRecords
=
relatedRecords
.
some
((
record
)
=>
record
.
isLocked
);
const
metadata
=
messageRecord
?.
metadata
||
{};
const
fieldMap
=
useMemo
(()
=>
{
...
...
@@ -227,6 +229,13 @@ export default function ProblemRectificationFormPage() {
return
;
}
const
latestRecord
=
await
loadRecord
(
selectedRecord
.
id
);
if
(
selectedRecord
.
isLocked
||
latestRecord
?.
metadata
?.
is_locked
===
true
)
{
setError
(
'当前问题整改记录已锁定,不允许修改。'
);
await
refreshAfterMutation
();
return
;
}
await
updateRecord
(
selectedRecord
.
id
,
{
metadata
:
{
[
fieldName
]:
...
...
@@ -246,6 +255,11 @@ export default function ProblemRectificationFormPage() {
return
;
}
if
(
hasLockedRecords
)
{
setError
(
'当前流程包含已锁定的问题整改记录,不允许继续修改或审批。'
);
return
;
}
setSubmitting
(
true
);
setError
(
''
);
...
...
@@ -307,8 +321,9 @@ export default function ProblemRectificationFormPage() {
});
};
const
actionHint
=
viewerRole
===
'editor'
const
actionHint
=
hasLockedRecords
?
'当前流程包含已锁定记录,仅可查看;解锁后方可继续处理。'
:
viewerRole
===
'editor'
?
'你当前是填写人,请完善整改内容后点击送审。'
:
viewerRole
===
'auditor'
?
'你当前是复核人,请核对整改内容后进行通过或驳回。'
...
...
@@ -418,7 +433,15 @@ export default function ProblemRectificationFormPage() {
{
relatedRecords
.
map
((
record
)
=>
(
<
TableRow
key=
{
record
.
id
}
>
<
TableCell
>
<
div
className=
"flex flex-wrap items-center gap-2"
>
<
div
className=
"font-medium text-slate-900"
>
{
record
.
title
||
'-'
}
</
div
>
{
record
.
isLocked
?
(
<
span
className=
"inline-flex items-center gap-1 rounded-full bg-amber-50 px-2.5 py-1 text-xs font-medium text-amber-700 ring-1 ring-amber-100"
>
<
LockClosedIcon
className=
"size-3.5"
aria
-
hidden=
"true"
/>
已锁定
</
span
>
)
:
null
}
</
div
>
<
div
className=
"mt-1 text-xs text-slate-500"
>
{
record
.
projectName
||
'-'
}
</
div
>
</
TableCell
>
<
TableCell
>
{
record
.
feedbackUnit
||
'-'
}
</
TableCell
>
...
...
@@ -437,7 +460,7 @@ export default function ProblemRectificationFormPage() {
outline
onClick=
{
()
=>
setSelectedRecord
(
record
)
}
>
{
canEditRecords
?
'查看/填写'
:
'查看详情'
}
{
canEditRecords
&&
!
record
.
isLocked
?
'查看/填写'
:
'查看详情'
}
</
Button
>
</
TableCell
>
</
TableRow
>
...
...
@@ -465,17 +488,17 @@ export default function ProblemRectificationFormPage() {
</
div
>
<
div
className=
"mt-5 flex flex-wrap gap-3"
>
{
currentStep
===
'editor'
&&
viewerRole
===
'editor'
?
(
<
Button
color=
"blue"
disabled=
{
submitting
||
relatedRecords
.
length
===
0
}
onClick=
{
handleEditorSubmit
}
>
<
Button
color=
"blue"
disabled=
{
submitting
||
hasLockedRecords
||
relatedRecords
.
length
===
0
}
onClick=
{
handleEditorSubmit
}
>
{
submitting
?
'送审中...'
:
'填写完成并送审'
}
</
Button
>
)
:
null
}
{
currentStep
===
'auditor'
&&
viewerRole
===
'auditor'
?
(
<>
<
Button
color=
"emerald"
disabled=
{
submitting
||
relatedRecords
.
length
===
0
}
onClick=
{
handleAuditorApprove
}
>
<
Button
color=
"emerald"
disabled=
{
submitting
||
hasLockedRecords
||
relatedRecords
.
length
===
0
}
onClick=
{
handleAuditorApprove
}
>
{
submitting
?
'处理中...'
:
'复核通过'
}
</
Button
>
<
Button
color=
"red"
disabled=
{
submitting
||
relatedRecords
.
length
===
0
}
onClick=
{
handleAuditorReject
}
>
<
Button
color=
"red"
disabled=
{
submitting
||
hasLockedRecords
||
relatedRecords
.
length
===
0
}
onClick=
{
handleAuditorReject
}
>
{
submitting
?
'处理中...'
:
'驳回复填'
}
</
Button
>
</>
...
...
@@ -483,10 +506,10 @@ export default function ProblemRectificationFormPage() {
{
currentStep
===
'sender'
&&
viewerRole
===
'sender'
?
(
<>
<
Button
color=
"blue"
disabled=
{
submitting
||
relatedRecords
.
length
===
0
}
onClick=
{
handleSenderApprove
}
>
<
Button
color=
"blue"
disabled=
{
submitting
||
hasLockedRecords
||
relatedRecords
.
length
===
0
}
onClick=
{
handleSenderApprove
}
>
{
submitting
?
'处理中...'
:
'最终审核通过'
}
</
Button
>
<
Button
color=
"red"
disabled=
{
submitting
||
relatedRecords
.
length
===
0
}
onClick=
{
handleSenderReject
}
>
<
Button
color=
"red"
disabled=
{
submitting
||
hasLockedRecords
||
relatedRecords
.
length
===
0
}
onClick=
{
handleSenderReject
}
>
{
submitting
?
'处理中...'
:
'最终审核驳回'
}
</
Button
>
</>
...
...
@@ -512,6 +535,11 @@ export default function ProblemRectificationFormPage() {
<
DialogBody
>
{
selectedRecord
?
(
<
div
className=
"space-y-4"
>
{
selectedRecord
.
isLocked
?
(
<
div
className=
"rounded-2xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800"
>
当前问题整改记录已锁定,仅可查看。
</
div
>
)
:
null
}
<
div
className=
"grid gap-4 md:grid-cols-2"
>
<
SummaryCard
label=
"问题标题"
value=
{
selectedRecord
.
title
||
'-'
}
/>
<
SummaryCard
label=
"反馈单位"
value=
{
selectedRecord
.
feedbackUnit
||
'-'
}
/>
...
...
@@ -526,8 +554,8 @@ export default function ProblemRectificationFormPage() {
label=
{
fieldDef
.
label
||
fieldDef
.
name
}
fieldDef=
{
fieldDef
}
value=
{
selectedRecord
.
raw
?.
metadata
?.[
fieldDef
.
name
]
}
readonly=
{
!
canEditRecords
}
disabled=
{
!
canEditRecords
}
readonly=
{
!
canEditRecords
||
selectedRecord
.
isLocked
}
disabled=
{
!
canEditRecords
||
selectedRecord
.
isLocked
}
onSave=
{
(
nextValue
)
=>
handleSaveField
(
fieldDef
.
name
,
nextValue
)
}
/>
))
}
...
...
src/pages/problem_rectification/list/index.jsx
View file @
3917767f
This diff is collapsed.
Click to expand it.
src/pages/problem_rectification/problem-rectification.business-flow.md
View file @
3917767f
This diff is collapsed.
Click to expand it.
src/pages/problem_rectification/problemRectificationDashboardService.js
View file @
3917767f
...
...
@@ -150,34 +150,29 @@ function normalizeRatingLevel(value) {
return
RATING_LEVELS
.
includes
(
text
)
?
text
:
''
;
}
function
calculateQualityRating
(
record
)
{
const
explicitRating
=
normalizeRatingLevel
(
record
.
overallRating
);
if
(
explicitRating
)
{
return
explicitRating
;
}
export
function
calculateRectificationQualityRating
(
record
)
{
const
dimensions
=
[
normalizeRatingLevel
(
record
.
timelinessLevel
),
normalizeRatingLevel
(
record
.
materialQualityLevel
),
record
.
involvesPolicyRevision
?
'高'
:
''
,
record
.
involvesSystemConstruction
?
'高'
:
''
,
record
.
isHistoricalProblem
?
'
低
'
:
''
,
record
.
isRepeatedProblem
?
'
低
'
:
''
,
record
.
isHistoricalProblem
?
'
高
'
:
''
,
record
.
isRepeatedProblem
?
'
高
'
:
''
,
].
filter
(
Boolean
);
if
(
dimensions
.
length
===
0
)
{
return
''
;
}
if
(
dimensions
.
includes
(
'低'
))
{
return
'低'
;
}
const
highCount
=
dimensions
.
filter
((
item
)
=>
item
===
'高'
).
length
;
if
(
highCount
>=
2
)
{
if
(
highCount
>=
1
)
{
return
'高'
;
}
if
(
dimensions
.
includes
(
'低'
))
{
return
'低'
;
}
return
'中'
;
}
...
...
@@ -468,7 +463,6 @@ function normalizeProblemRecord(record) {
rootCause
:
normalizeText
(
metadata
.
problem_root_cause
),
timelinessLevel
:
normalizeText
(
metadata
.
rectification_timeliness_level
),
materialQualityLevel
:
normalizeText
(
metadata
.
rectification_material_quality_level
),
overallRating
:
normalizeText
(
metadata
.
rectification_overall_rating
),
primaryResponsibleDepartment
:
extractPrimaryDepartment
(
metadata
),
responsibleDepartments
:
toArray
(
metadata
.
responsible_department
)
.
map
((
item
)
=>
normalizeText
(
item
))
...
...
@@ -500,7 +494,7 @@ function normalizeProblemRecord(record) {
return
{
...
normalizedRecord
,
qualityRating
:
calculateQualityRating
(
normalizedRecord
),
qualityRating
:
calculate
Rectification
QualityRating
(
normalizedRecord
),
};
}
...
...
src/pages/problem_rectification/problemRectificationFormService.js
View file @
3917767f
...
...
@@ -153,6 +153,29 @@ function buildReturnUrl(messageName) {
return
getProblemRectificationFormUrl
(
messageName
);
}
async
function
assertRelatedRecordsUnlocked
(
messageRecord
)
{
const
metadata
=
messageRecord
?.
metadata
||
{};
const
recordIds
=
normalizeRestrictionValue
(
metadata
.
restriction_value
);
if
(
recordIds
.
length
===
0
)
{
return
;
}
const
lockedResult
=
await
queryRecords
({
subject
:
metadata
.
subject_name
||
'problem_rectification'
,
page
:
0
,
page_size
:
1
,
mode
:
'lean'
,
filter
:
{
_id
:
{
$in
:
recordIds
},
'metadata.is_locked'
:
true
,
},
});
if
((
lockedResult
?.
records
||
[]).
length
>
0
)
{
throw
new
Error
(
'当前流程包含已锁定的问题整改记录,不允许继续修改或审批。'
);
}
}
function
resolveCurrentStep
(
messageRecord
)
{
const
metadata
=
messageRecord
?.
metadata
||
{};
const
editorStatus
=
metadata
.
editor_status
||
DEFAULT_STATUS
;
...
...
@@ -280,6 +303,7 @@ export async function markEditorComplete({
currentUser
,
auditors
,
})
{
await
assertRelatedRecordsUnlocked
(
messageRecord
);
const
metadata
=
messageRecord
?.
metadata
||
{};
const
messageName
=
messageRecord
?.
name
||
messageRecord
?.
_id
;
const
returnUrl
=
buildReturnUrl
(
messageName
);
...
...
@@ -324,6 +348,7 @@ export async function approveByAuditor({
currentUser
,
sender
,
})
{
await
assertRelatedRecordsUnlocked
(
messageRecord
);
const
metadata
=
messageRecord
?.
metadata
||
{};
const
messageName
=
messageRecord
?.
name
||
messageRecord
?.
_id
;
const
returnUrl
=
buildReturnUrl
(
messageName
);
...
...
@@ -368,6 +393,7 @@ export async function rejectByAuditor({
currentUser
,
editors
,
})
{
await
assertRelatedRecordsUnlocked
(
messageRecord
);
const
metadata
=
messageRecord
?.
metadata
||
{};
const
messageName
=
messageRecord
?.
name
||
messageRecord
?.
_id
;
const
returnUrl
=
buildReturnUrl
(
messageName
);
...
...
@@ -411,6 +437,7 @@ export async function rejectByAuditor({
export
async
function
approveBySender
({
messageRecord
,
})
{
await
assertRelatedRecordsUnlocked
(
messageRecord
);
const
metadata
=
messageRecord
?.
metadata
||
{};
await
batchUpdateRecords
({
...
...
@@ -437,6 +464,7 @@ export async function rejectBySender({
currentUser
,
editors
,
})
{
await
assertRelatedRecordsUnlocked
(
messageRecord
);
const
metadata
=
messageRecord
?.
metadata
||
{};
const
messageName
=
messageRecord
?.
name
||
messageRecord
?.
_id
;
const
returnUrl
=
buildReturnUrl
(
messageName
);
...
...
src/pages/problem_rectification/problemRectificationListService.js
View file @
3917767f
This diff is collapsed.
Click to expand it.
src/services/subjectsDefinition.md
View file @
3917767f
...
...
@@ -103,7 +103,7 @@ type Record = {
一条记录表示一条待整改问题主记录,是本模块最核心的数据对象。
当前字段定义来自线上 Subject 配置
,共 43 个字段
。字段值写入时均放入
`metadata`
。
当前字段定义来自线上 Subject 配置。字段值写入时均放入
`metadata`
。
| 字段标签 | 字段别名 | 字段类型 | 默认值 | 是否主键 | 是否多值 | 是否必填 | 可搜索 | 可聚合 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
...
...
@@ -151,6 +151,8 @@ type Record = {
| 实际检查完成日期 |
`inspection_completed_at`
| text |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 主责部门 |
`primary_responsible_department`
| text |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 部门整改明细 |
`department_rectification_items`
| object |
`[]`
| 否 | 是 | 否 | 否 | 否 |
| 延期申请 |
`problem_rectification_delay_request`
| subject |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 状态锁定 |
`is_locked`
| boolean |
`false`
| 否 | 否 | 否 | 否 | 否 |
### 3.1.1 select 字段选项
...
...
@@ -175,6 +177,8 @@ type Record = {
-
其余
`select`
类型的可选值必须以线上 Subject 配置中的
`settings.options`
为准,禁止在页面内硬编码
-
`problem_discovery_situation`
曾在历史文档和归档对象中出现,但本次主对象字段定义未包含;新页面只应在 Subject View 或线上字段配置存在时展示,不能作为
`problem_rectification`
固定字段依赖
-
`department_rectification_items`
用于新转发流程的部门级整改明细。单条问题即使只有 1 个责任部门,也生成 1 条明细;转发后
`rectification_progress`
、
`rectification_situation`
、
`the_time_of_rectification`
、
`rectification_proof_materials`
、
`audit_status`
、
`final_audit_status`
以明细为事实来源,父字段仅做兼容汇总展示
-
`problem_rectification_delay_request`
为问题主记录的单次延期申请嵌套对象,与
`department_rectification_items`
平级;发起延期不要求已有部门整改明细
-
`is_locked`
为问题整改主记录的状态锁定标记;仅整改进度汇总值为
`已整改`
的记录允许写入
`true`
,锁定后所有业务字段和流程状态均不可修改,只有解锁操作可以将其写回
`false`
-
部门明细的填写人只能编辑自己负责明细的整改业务字段,送审后(
`editor_status = "已完成"`
)不再允许编辑;审批人审批通过后(
`audit_status = "已审批"`
)不再允许编辑,审批驳回后(
`audit_status = "已驳回"`
)审批人可以编辑该明细的整改业务字段,填写人也恢复编辑。审批人恢复的只是业务字段编辑权限,不获得填写人的送审权限。流程推送人可以编辑本次推送关联的父问题记录及全部部门明细整改业务字段。审批状态、待办 ID、明细 ID 等流程控制字段不作为普通表单字段开放
-
推送人修改父问题记录或部门明细时,不自动重置该明细已经形成的审批状态,也不自动重新生成流程待办
...
...
@@ -188,6 +192,7 @@ type Record = {
| 审批人 |
`auditor`
| user | 是 | 保存用户
`_id`
,每条明细 1 个审批人 |
| 整改进度 |
`rectification_progress`
| select/text | 否 | 填写人维护,优先使用主对象整改进度选项 |
| 整改情况 |
`rectification_situation`
| long_text | 否 | 填写人维护 |
| 延期事由(兼容) |
`delay_reason`
| long_text | 否 | 已存在的明细字段;新延期流程改为写入问题主记录平级嵌套对象的同名字段,本字段仅保留兼容数据 |
| 预计整改完成时间 |
`the_time_of_rectification`
| date | 否 | 填写人维护,提交时保存 ISO 8601 |
| 整改证明材料 |
`rectification_proof_materials`
| file | 否 | 填写人上传,按部门明细独立保存 |
| 填写状态 |
`editor_status`
| text | 否 |
`未完成`
、
`已完成`
|
...
...
@@ -199,7 +204,39 @@ type Record = {
| 更新人 |
`updated_by`
| user | 否 | 最近更新用户
`_id`
|
| 更新时间 |
`updated_at`
| date | 否 | 最近更新时间 |
### 3.1.4 metadata 示例
### 3.1.4 `problem_rectification_delay_request` 嵌套对象
-
**subject**
:
`problem_rectification_delay_request`
-
**父级路径**
:
`metadata.problem_rectification_delay_request`
| 字段标签 | 字段别名 | 字段类型 | 是否必填 | 说明 |
| --- | --- | --- | --- | --- |
| 原预计完成时间 |
`original_due_date`
| date | 否 | 发起申请时从问题主记录
`the_time_of_rectification`
复制,保存 ISO 8601 |
| 申请完成时间 |
`requested_due_date`
| date | 否 | 填写人填写;提交申请时必填并保存 ISO 8601 |
| 延期事由 |
`delay_reason`
| long_text | 否 | 填写人填写;提交申请时必填 |
| 填写人 |
`editor`
| user | 否 | 保存推送时选择的填写人
`_id`
|
| 一级审批人 |
`auditor`
| user | 否 | 保存推送时选择的一级审批人
`_id`
|
| 最终审批人 |
`sender`
| user | 否 | 保存延期申请推送人
`_id`
|
| 填写状态 |
`editor_status`
| select/text | 否 |
`未完成`
、
`已完成`
|
| 一级审批状态 |
`auditor_status`
| select/text | 否 |
`未审批`
、
`已审批`
、
`已驳回`
|
| 最终审批状态 |
`sender_status`
| select/text | 否 |
`未审批`
、
`已审批`
、
`已驳回`
|
| 填写待办 ID |
`progress_id_editor`
| text | 否 | 当前延期申请填写 OA 待办 ID |
| 一级审批待办 ID |
`progress_id_auditor`
| text | 否 | 当前延期申请一级审批 OA 待办 ID |
| 最终审批待办 ID |
`progress_id_sender`
| text | 否 | 当前延期申请最终审批 OA 待办 ID |
| 流程主单 ID |
`flow_record_id`
| text | 否 | 对应
`message_reference_id`
的
`name`
或
`_id`
|
| 提交时间 |
`submitted_at`
| date | 否 | 填写人最近一次提交时间 |
| 一级审批时间 |
`auditor_decided_at`
| date | 否 | 一级审批人最近一次审批时间 |
| 最终审批时间 |
`sender_decided_at`
| date | 否 | 最终审批人最近一次审批时间 |
写入约定:
-
延期申请发起时只初始化问题主记录的嵌套对象和填写人 OA 待办,不修改主记录
`the_time_of_rectification`
-
`requested_due_date`
、
`delay_reason`
在保存草稿时可以为空,在提交申请时由前端强制校验必填
-
一级审批或最终审批驳回后,
`editor_status`
重置为
`未完成`
,并重新创建填写人 OA 待办
-
只有
`sender_status = "已审批"`
时,才把
`requested_due_date`
写回问题主记录
`the_time_of_rectification`
-
同一问题主记录已有该嵌套对象时,不允许再次创建另一份延期申请
### 3.1.5 metadata 示例
```
json
{
...
...
@@ -326,7 +363,7 @@ type Record = {
-
`restriction_value`
保存被推送整改记录的
`_id[]`
-
`reference_record_id`
与
`restriction_value`
保持一致,作为显式的“关联记录 ID”冗余字段
-
`subject_name`
保存被推送记录所属对象名,当前整改流程固定为
`problem_rectification`
-
`flow_mode`
区分
新旧流程:
`department`
表示单条问题按责任部门生成明细行,
`batch`
表示多选问题的单填写人 / 单审批人简单推送;历史数据可能为空
-
`flow_mode`
区分
流程:
`department`
表示单条问题按责任部门生成整改明细行,
`batch`
表示多选问题的单填写人 / 单审批人简单推送,
`delay`
表示问题级延期申请;历史
`delay_department`
值仅保留页面识别兼容
-
`department_item_ids`
保存本次部门流程涉及的
`department_rectification_items[].item_id`
-
`progress_id_editor`
、
`progress_id_auditor`
、
`progress_id_sender`
用于记录每一步用户确认动作生成的流程 ID,用来区分当前流程推进到了哪一步
-
`editor_status`
:当前项目统一使用
`未完成`
、
`已完成`
...
...
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