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
004e66ec
Commit
004e66ec
authored
Aug 03, 2026
by
David Yang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 支持部门级延期申请
parent
3917767f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
334 additions
and
44 deletions
+334
-44
index.jsx
src/components/record-workbench/index.jsx
+95
-2
index.jsx
src/pages/problem_rectification/flow-table/index.jsx
+105
-2
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
problemRectificationListService.js
.../problem_rectification/problemRectificationListService.js
+118
-30
subjectsDefinition.md
src/services/subjectsDefinition.md
+16
-10
No files found.
src/components/record-workbench/index.jsx
View file @
004e66ec
...
@@ -466,6 +466,7 @@ export default function RecordWorkbench({
...
@@ -466,6 +466,7 @@ export default function RecordWorkbench({
states
=
{},
states
=
{},
renderCell
,
renderCell
,
renderExpandedRow
,
renderExpandedRow
,
getExpandedRecordRows
,
isRowExpandable
,
isRowExpandable
,
getRecordId
=
defaultGetRecordId
,
getRecordId
=
defaultGetRecordId
,
getRecordLabel
=
defaultGetRecordLabel
,
getRecordLabel
=
defaultGetRecordLabel
,
...
@@ -534,7 +535,8 @@ export default function RecordWorkbench({
...
@@ -534,7 +535,8 @@ export default function RecordWorkbench({
);
);
const
hasColumnGroups
=
columnGroupMeta
.
groups
.
length
>
0
;
const
hasColumnGroups
=
columnGroupMeta
.
groups
.
length
>
0
;
const
showColumnGroupHeader
=
columnGroupSegments
.
some
((
segment
)
=>
segment
.
group
);
const
showColumnGroupHeader
=
columnGroupSegments
.
some
((
segment
)
=>
segment
.
group
);
const
hasExpandableRows
=
typeof
renderExpandedRow
===
'function'
;
const
hasExpandedRecordRows
=
typeof
getExpandedRecordRows
===
'function'
;
const
hasExpandableRows
=
hasExpandedRecordRows
||
typeof
renderExpandedRow
===
'function'
;
const
hasExpandColumn
=
hasExpandableRows
&&
showExpandColumn
;
const
hasExpandColumn
=
hasExpandableRows
&&
showExpandColumn
;
const
tableColSpan
=
const
tableColSpan
=
stickyColumns
.
orderedColumns
.
length
+
stickyColumns
.
orderedColumns
.
length
+
...
@@ -997,6 +999,21 @@ export default function RecordWorkbench({
...
@@ -997,6 +999,21 @@ export default function RecordWorkbench({
openDetail
,
openDetail
,
};
};
const
visibleRowActions
=
rowActions
.
filter
((
action
)
=>
!
isActionHidden
(
action
,
rowContext
));
const
visibleRowActions
=
rowActions
.
filter
((
action
)
=>
!
isActionHidden
(
action
,
rowContext
));
const
expandedRecordRows
=
(()
=>
{
if
(
!
expanded
||
!
expandable
||
!
hasExpandedRecordRows
)
{
return
EMPTY_ARRAY
;
}
const
nextExpandedRecordRows
=
getExpandedRecordRows
({
record
,
rowContext
,
columns
:
stickyColumns
.
orderedColumns
,
});
return
Array
.
isArray
(
nextExpandedRecordRows
)
?
nextExpandedRecordRows
:
EMPTY_ARRAY
;
})();
return
(
return
(
<
Fragment
key=
{
recordId
}
>
<
Fragment
key=
{
recordId
}
>
...
@@ -1101,7 +1118,83 @@ export default function RecordWorkbench({
...
@@ -1101,7 +1118,83 @@ export default function RecordWorkbench({
</
TableCell
>
</
TableCell
>
)
:
null
}
)
:
null
}
</
TableRow
>
</
TableRow
>
{
expanded
&&
expandable
?
(
{
expanded
&&
expandable
&&
hasExpandedRecordRows
?
(
expandedRecordRows
.
map
((
expandedRecord
,
expandedIndex
)
=>
{
const
expandedRecordId
=
expandedRecord
?.
key
||
expandedRecord
?.
id
||
expandedRecord
?.
_id
||
`${recordId}-expanded-${expandedIndex}`
;
return
(
<
TableRow
key=
{
expandedRecordId
}
className=
"align-top bg-rose-50/35"
>
{
selectable
?
(
<
TableCell
className=
"align-top sticky left-0 z-30 bg-rose-50/95 shadow-[10px_0_20px_rgba(15,23,42,0.05)]"
style=
{
{
width
:
SELECTION_COLUMN_WIDTH
,
minWidth
:
SELECTION_COLUMN_WIDTH
}
}
/>
)
:
null
}
{
hasExpandColumn
?
(
<
TableCell
className=
"w-12 align-top bg-rose-50/70"
style=
{
{
width
:
48
,
minWidth
:
48
}
}
/>
)
:
null
}
{
stickyColumns
.
orderedColumns
.
map
((
column
)
=>
{
const
stickyMeta
=
stickyColumns
.
stickyMeta
[
column
.
field
];
return
(
<
TableCell
key=
{
column
.
field
}
style=
{
{
width
:
column
.
width
||
180
,
minWidth
:
Math
.
min
(
Math
.
max
(
column
.
width
||
180
,
150
),
360
),
left
:
stickyMeta
?.
side
===
'left'
?
`${stickyMeta.offset}px`
:
undefined
,
right
:
stickyMeta
?.
side
===
'right'
?
`${stickyMeta.offset}px`
:
undefined
,
}
}
className=
{
clsx
(
'align-top'
,
getStickyCellClass
(
stickyMeta
),
)
}
>
{
(()
=>
{
if
(
column
.
render
)
{
return
column
.
render
(
expandedRecord
,
column
);
}
if
(
renderCell
)
{
const
customNode
=
renderCell
({
record
:
expandedRecord
,
column
,
expandable
:
false
,
expanded
:
false
,
toggleExpanded
:
()
=>
{},
parentRecord
:
record
,
isExpandedRecord
:
true
,
});
if
(
customNode
!==
undefined
)
{
return
customNode
;
}
}
return
defaultRenderCell
(
expandedRecord
,
column
);
})()
}
</
TableCell
>
);
})
}
{
visibleRowActions
.
length
>
0
?
(
<
TableCell
className=
"align-top sticky right-0 z-30 bg-rose-50/95 shadow-[-10px_0_20px_rgba(15,23,42,0.05)]"
style=
{
{
width
:
actionColumnWidth
,
minWidth
:
actionColumnWidth
}
}
/>
)
:
null
}
</
TableRow
>
);
})
)
:
null
}
{
expanded
&&
expandable
&&
!
hasExpandedRecordRows
?
(
<
TableRow
key=
{
`${recordId}-expanded`
}
className=
"bg-zinc-50/70"
>
<
TableRow
key=
{
`${recordId}-expanded`
}
className=
"bg-zinc-50/70"
>
<
TableCell
colSpan=
{
tableColSpan
}
className=
"px-6 py-4"
>
<
TableCell
colSpan=
{
tableColSpan
}
className=
"px-6 py-4"
>
{
renderExpandedRow
({
record
,
rowContext
})
}
{
renderExpandedRow
({
record
,
rowContext
})
}
...
...
src/pages/problem_rectification/flow-table/index.jsx
View file @
004e66ec
...
@@ -34,6 +34,7 @@ import {
...
@@ -34,6 +34,7 @@ import {
AUDIT_STATUS_PENDING
,
AUDIT_STATUS_PENDING
,
AUDIT_STATUS_REJECTED
,
AUDIT_STATUS_REJECTED
,
DELAY_REQUEST_FIELD
,
DELAY_REQUEST_FIELD
,
DELAY_REQUEST_ITEMS_FIELD
,
EDITOR_STATUS_COMPLETED
,
EDITOR_STATUS_COMPLETED
,
EDITOR_STATUS_PENDING
,
EDITOR_STATUS_PENDING
,
FLOW_MODE_BATCH
,
FLOW_MODE_BATCH
,
...
@@ -41,9 +42,11 @@ import {
...
@@ -41,9 +42,11 @@ import {
FLOW_MODE_DELAY_DEPARTMENT
,
FLOW_MODE_DELAY_DEPARTMENT
,
FLOW_MODE_DEPARTMENT
,
FLOW_MODE_DEPARTMENT
,
PROBLEM_RECTIFICATION_SUBJECT
,
PROBLEM_RECTIFICATION_SUBJECT
,
buildDepartmentParentMetadataPatch
,
buildDepartmentParentBatchUpdateData
,
buildDepartmentParentBatchUpdateData
,
getProblemRectificationFlowTableUrl
,
getProblemRectificationFlowTableUrl
,
normalizeDelayRequest
,
normalizeDelayRequest
,
normalizeDelayRequestItems
,
normalizeDepartmentRectificationItems
,
normalizeDepartmentRectificationItems
,
}
from
'../problemRectificationListService'
;
}
from
'../problemRectificationListService'
;
...
@@ -54,6 +57,7 @@ const FLOW_MANAGED_PARENT_FIELDS = [
...
@@ -54,6 +57,7 @@ const FLOW_MANAGED_PARENT_FIELDS = [
'final_audit_status'
,
'final_audit_status'
,
'department_rectification_items'
,
'department_rectification_items'
,
DELAY_REQUEST_FIELD
,
DELAY_REQUEST_FIELD
,
DELAY_REQUEST_ITEMS_FIELD
,
];
];
const
DEPARTMENT_MANAGED_PARENT_FIELDS
=
[
const
DEPARTMENT_MANAGED_PARENT_FIELDS
=
[
...
FLOW_MANAGED_PARENT_FIELDS
,
...
FLOW_MANAGED_PARENT_FIELDS
,
...
@@ -248,12 +252,50 @@ function buildBatchRows(records = [], metadata = {}) {
...
@@ -248,12 +252,50 @@ function buildBatchRows(records = [], metadata = {}) {
});
});
}
}
function
buildDelayRows
(
records
=
[],
metadata
=
{})
{
function
buildDelayRows
(
records
=
[],
metadata
=
{}
,
flowMode
=
FLOW_MODE_DELAY
)
{
const
editor
=
toId
(
toArray
(
metadata
.
editor
)[
0
]);
const
editor
=
toId
(
toArray
(
metadata
.
editor
)[
0
]);
const
auditor
=
toId
(
toArray
(
metadata
.
auditor
)[
0
]);
const
auditor
=
toId
(
toArray
(
metadata
.
auditor
)[
0
]);
const
scopedItemIds
=
new
Set
(
toArray
(
metadata
.
department_item_ids
).
map
(
toId
).
filter
(
Boolean
));
return
records
.
flatMap
((
record
)
=>
{
return
records
.
flatMap
((
record
)
=>
{
const
recordMetadata
=
record
.
metadata
||
{};
const
recordMetadata
=
record
.
metadata
||
{};
if
(
flowMode
===
FLOW_MODE_DELAY_DEPARTMENT
)
{
return
normalizeDelayRequestItems
(
recordMetadata
[
DELAY_REQUEST_ITEMS_FIELD
])
.
filter
(
(
request
)
=>
scopedItemIds
.
size
===
0
||
scopedItemIds
.
has
(
request
.
item_id
)
||
scopedItemIds
.
has
(
request
.
source_department_item_id
),
)
.
map
((
request
)
=>
({
key
:
`
${
record
.
_id
||
record
.
name
}
-delay-
${
request
.
item_id
}
`
,
flowMode
:
FLOW_MODE_DELAY_DEPARTMENT
,
record
,
item
:
request
,
itemId
:
request
.
item_id
,
sourceDepartmentItemId
:
request
.
source_department_item_id
||
request
.
item_id
,
recordId
:
record
.
_id
||
record
.
name
,
title
:
record
.
title
||
recordMetadata
.
project_name
||
'-'
,
projectName
:
recordMetadata
.
project_name
||
'-'
,
problemBrief
:
recordMetadata
.
problem_brief
||
''
,
relatedIssueDomain
:
toArray
(
recordMetadata
.
related_issue_domain
).
join
(
'、'
),
department
:
request
.
responsible_department
||
'-'
,
editor
:
request
.
editor
||
editor
,
auditor
:
request
.
auditor
||
auditor
,
sender
:
request
.
sender
||
toId
(
metadata
.
sender
),
originalDueDate
:
request
.
original_due_date
||
''
,
requestedDueDate
:
request
.
requested_due_date
||
''
,
delayReason
:
request
.
delay_reason
||
''
,
editorStatus
:
request
.
editor_status
||
EDITOR_STATUS_PENDING
,
auditStatus
:
request
.
auditor_status
||
AUDIT_STATUS_PENDING
,
finalAuditStatus
:
request
.
sender_status
||
AUDIT_STATUS_PENDING
,
progressIdEditor
:
request
.
progress_id_editor
||
''
,
progressIdAuditor
:
request
.
progress_id_auditor
||
''
,
progressIdSender
:
request
.
progress_id_sender
||
''
,
isLocked
:
recordMetadata
.
is_locked
===
true
,
}));
}
const
request
=
normalizeDelayRequest
(
recordMetadata
[
DELAY_REQUEST_FIELD
]);
const
request
=
normalizeDelayRequest
(
recordMetadata
[
DELAY_REQUEST_FIELD
]);
if
(
!
request
)
{
if
(
!
request
)
{
return
[];
return
[];
...
@@ -308,7 +350,7 @@ export default function ProblemRectificationFlowTablePage() {
...
@@ -308,7 +350,7 @@ export default function ProblemRectificationFlowTablePage() {
const
rows
=
useMemo
(
const
rows
=
useMemo
(
()
=>
{
()
=>
{
if
(
flowMode
===
FLOW_MODE_DELAY
||
flowMode
===
FLOW_MODE_DELAY_DEPARTMENT
)
{
if
(
flowMode
===
FLOW_MODE_DELAY
||
flowMode
===
FLOW_MODE_DELAY_DEPARTMENT
)
{
return
buildDelayRows
(
records
,
metadata
);
return
buildDelayRows
(
records
,
metadata
,
flowMode
);
}
}
return
flowMode
===
FLOW_MODE_DEPARTMENT
return
flowMode
===
FLOW_MODE_DEPARTMENT
?
buildDepartmentRows
(
records
)
?
buildDepartmentRows
(
records
)
...
@@ -453,6 +495,67 @@ export default function ProblemRectificationFlowTablePage() {
...
@@ -453,6 +495,67 @@ export default function ProblemRectificationFlowTablePage() {
throw
new
Error
(
'当前问题整改记录已锁定,不允许继续修改或审批。'
);
throw
new
Error
(
'当前问题整改记录已锁定,不允许继续修改或审批。'
);
}
}
if
(
row
.
flowMode
===
FLOW_MODE_DELAY_DEPARTMENT
)
{
const
currentRequests
=
normalizeDelayRequestItems
(
latestRecord
?.
metadata
?.[
DELAY_REQUEST_ITEMS_FIELD
],
);
const
currentRequest
=
currentRequests
.
find
(
(
request
)
=>
request
.
item_id
===
row
.
itemId
||
request
.
source_department_item_id
===
row
.
sourceDepartmentItemId
,
);
if
(
!
currentRequest
)
{
throw
new
Error
(
'当前部门延期申请不存在,请刷新后重试。'
);
}
const
currentFlowIds
=
[
messageRecord
?.
name
,
messageRecord
?.
_id
,
messageId
].
filter
(
Boolean
);
if
(
currentRequest
.
flow_record_id
&&
!
currentFlowIds
.
includes
(
currentRequest
.
flow_record_id
)
)
{
throw
new
Error
(
'当前部门延期申请已关联其他流程,请刷新后重试。'
);
}
const
nextRequests
=
currentRequests
.
map
((
request
)
=>
request
.
item_id
===
currentRequest
.
item_id
?
{
...
request
,
...
requestPatch
,
}
:
request
,
);
const
metadataPatch
=
{
[
DELAY_REQUEST_ITEMS_FIELD
]:
nextRequests
,
};
if
(
recordPatch
.
the_time_of_rectification
)
{
const
currentDepartmentItems
=
normalizeDepartmentRectificationItems
(
latestRecord
);
const
sourceDepartmentItemId
=
row
.
sourceDepartmentItemId
||
row
.
itemId
;
if
(
currentDepartmentItems
.
length
>
0
)
{
const
nextDepartmentItems
=
currentDepartmentItems
.
map
((
item
)
=>
item
.
item_id
===
sourceDepartmentItemId
?
{
...
item
,
the_time_of_rectification
:
recordPatch
.
the_time_of_rectification
,
updated_by
:
currentUserId
,
updated_at
:
dayjs
().
toISOString
(),
}
:
item
,
);
Object
.
assign
(
metadataPatch
,
buildDepartmentParentMetadataPatch
(
nextDepartmentItems
));
}
else
{
metadataPatch
.
the_time_of_rectification
=
recordPatch
.
the_time_of_rectification
;
}
}
await
updateRecord
(
row
.
recordId
,
{
metadata
:
metadataPatch
,
});
return
;
}
const
currentRequest
=
normalizeDelayRequest
(
const
currentRequest
=
normalizeDelayRequest
(
latestRecord
?.
metadata
?.[
DELAY_REQUEST_FIELD
],
latestRecord
?.
metadata
?.[
DELAY_REQUEST_FIELD
],
);
);
...
...
src/pages/problem_rectification/list/index.jsx
View file @
004e66ec
This diff is collapsed.
Click to expand it.
src/pages/problem_rectification/problem-rectification.business-flow.md
View file @
004e66ec
This diff is collapsed.
Click to expand it.
src/pages/problem_rectification/problemRectificationListService.js
View file @
004e66ec
...
@@ -29,6 +29,7 @@ export const PROBLEM_RECTIFICATION_PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
...
@@ -29,6 +29,7 @@ export const PROBLEM_RECTIFICATION_PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
export
const
DEFAULT_PROBLEM_RECTIFICATION_PAGE_SIZE
=
20
;
export
const
DEFAULT_PROBLEM_RECTIFICATION_PAGE_SIZE
=
20
;
export
const
DEPARTMENT_RECTIFICATION_FIELD
=
'department_rectification_items'
;
export
const
DEPARTMENT_RECTIFICATION_FIELD
=
'department_rectification_items'
;
export
const
DELAY_REQUEST_FIELD
=
'problem_rectification_delay_request'
;
export
const
DELAY_REQUEST_FIELD
=
'problem_rectification_delay_request'
;
export
const
DELAY_REQUEST_ITEMS_FIELD
=
'problem_rectification_delay_request_items'
;
export
const
FLOW_MODE_DEPARTMENT
=
'department'
;
export
const
FLOW_MODE_DEPARTMENT
=
'department'
;
export
const
FLOW_MODE_BATCH
=
'batch'
;
export
const
FLOW_MODE_BATCH
=
'batch'
;
export
const
FLOW_MODE_DELAY
=
'delay'
;
export
const
FLOW_MODE_DELAY
=
'delay'
;
...
@@ -40,6 +41,8 @@ export const AUDIT_STATUS_PENDING = '未审批';
...
@@ -40,6 +41,8 @@ export const AUDIT_STATUS_PENDING = '未审批';
export
const
AUDIT_STATUS_APPROVED
=
'已审批'
;
export
const
AUDIT_STATUS_APPROVED
=
'已审批'
;
export
const
AUDIT_STATUS_REJECTED
=
'已驳回'
;
export
const
AUDIT_STATUS_REJECTED
=
'已驳回'
;
const
FIXED_PROGRESS_VALUES
=
new
Set
([
'已整改'
,
'已优化'
]);
const
FIXED_PROGRESS_VALUES
=
new
Set
([
'已整改'
,
'已优化'
]);
const
RECTIFICATION_PROGRESS_PRIORITY
=
[
'整改中'
,
'部分整改'
,
'已整改'
,
'已优化'
,
'已完成'
,
'不适用'
];
const
AUDIT_STATUS_PRIORITY
=
[
AUDIT_STATUS_REJECTED
,
AUDIT_STATUS_PENDING
,
AUDIT_STATUS_APPROVED
];
const
LEVEL_ORDER
=
[
'高'
,
'中'
,
'低'
];
const
LEVEL_ORDER
=
[
'高'
,
'中'
,
'低'
];
const
FILTER_FIELD_PATHS
=
{
const
FILTER_FIELD_PATHS
=
{
progress
:
'metadata.rectification_progress'
,
progress
:
'metadata.rectification_progress'
,
...
@@ -132,18 +135,36 @@ function makeDepartmentItemId(record, department, index) {
...
@@ -132,18 +135,36 @@ function makeDepartmentItemId(record, department, index) {
return
`dept_
${
recordId
}
_
${
index
+
1
}
_
${
departmentSlug
}
_
${
Date
.
now
()}
_
${
randomPart
}
`
;
return
`dept_
${
recordId
}
_
${
index
+
1
}
_
${
departmentSlug
}
_
${
Date
.
now
()}
_
${
randomPart
}
`
;
}
}
function
summarize
TextStatus
(
values
=
[],
partialText
=
'部分审批'
,
emptyText
=
''
)
{
function
summarize
LaggingStatus
(
values
=
[],
priority
=
[],
emptyText
=
''
,
unknownRank
=
1
)
{
const
normalizedValues
=
uniqueTruthy
(
values
);
const
normalizedValues
=
values
.
map
((
value
)
=>
normalizeText
(
value
)
);
if
(
normalizedValues
.
length
===
0
)
{
if
(
normalizedValues
.
length
===
0
)
{
return
emptyText
;
return
emptyText
;
}
}
if
(
normalizedValues
.
length
===
1
)
{
const
priorityRank
=
new
Map
(
priority
.
map
((
status
,
index
)
=>
[
status
,
index
]));
return
normalizedValues
[
0
];
const
getStatusRank
=
(
status
)
=>
{
}
if
(
!
status
)
{
return
-
1
;
}
return
priorityRank
.
has
(
status
)
?
priorityRank
.
get
(
status
)
:
unknownRank
;
};
return
partialText
;
return
normalizedValues
.
reduce
((
laggingStatus
,
status
)
=>
{
const
nextStatus
=
status
||
emptyText
;
return
getStatusRank
(
nextStatus
)
<
getStatusRank
(
laggingStatus
)
?
nextStatus
:
laggingStatus
;
},
normalizedValues
[
0
]
||
emptyText
);
}
function
summarizeDepartmentProgress
(
values
=
[])
{
return
summarizeLaggingStatus
(
values
,
RECTIFICATION_PROGRESS_PRIORITY
,
''
,
1
);
}
function
summarizeDepartmentAuditStatus
(
values
=
[])
{
return
summarizeLaggingStatus
(
values
,
AUDIT_STATUS_PRIORITY
,
AUDIT_STATUS_PENDING
,
1
);
}
}
function
summarizeDate
(
values
=
[])
{
function
summarizeDate
(
values
=
[])
{
...
@@ -240,6 +261,9 @@ export function normalizeDelayRequest(value) {
...
@@ -240,6 +261,9 @@ export function normalizeDelayRequest(value) {
return
{
return
{
...
parsedValue
,
...
parsedValue
,
item_id
:
normalizeText
(
parsedValue
.
item_id
),
source_department_item_id
:
normalizeText
(
parsedValue
.
source_department_item_id
),
responsible_department
:
normalizeText
(
parsedValue
.
responsible_department
),
original_due_date
:
parsedValue
.
original_due_date
||
null
,
original_due_date
:
parsedValue
.
original_due_date
||
null
,
requested_due_date
:
parsedValue
.
requested_due_date
||
null
,
requested_due_date
:
parsedValue
.
requested_due_date
||
null
,
delay_reason
:
normalizeText
(
parsedValue
.
delay_reason
),
delay_reason
:
normalizeText
(
parsedValue
.
delay_reason
),
...
@@ -259,8 +283,41 @@ export function normalizeDelayRequest(value) {
...
@@ -259,8 +283,41 @@ export function normalizeDelayRequest(value) {
};
};
}
}
export
function
normalizeDelayRequestItems
(
value
)
{
let
parsedValue
=
value
;
if
(
typeof
value
===
'string'
)
{
try
{
parsedValue
=
JSON
.
parse
(
value
);
}
catch
(
error
)
{
return
[];
}
}
return
toArray
(
parsedValue
)
.
map
((
item
)
=>
normalizeDelayRequest
(
item
))
.
filter
(
Boolean
)
.
map
((
item
,
index
)
=>
({
...
item
,
item_id
:
item
.
item_id
||
item
.
source_department_item_id
||
`delay_item_
${
index
+
1
}
`
,
responsible_department
:
item
.
responsible_department
||
'未指定责任部门'
,
}));
}
export
function
buildDepartmentAssignmentsFromRecord
(
record
)
{
export
function
buildDepartmentAssignmentsFromRecord
(
record
)
{
const
metadata
=
record
?.
metadata
||
record
?.
raw
?.
metadata
||
{};
const
metadata
=
record
?.
metadata
||
record
?.
raw
?.
metadata
||
{};
const
departmentItems
=
normalizeDepartmentRectificationItems
(
record
);
if
(
departmentItems
.
length
>
0
)
{
return
departmentItems
.
map
((
item
,
index
)
=>
({
item_id
:
item
.
item_id
||
makeDepartmentItemId
(
record
?.
raw
||
record
,
item
.
responsible_department
,
index
),
source_department_item_id
:
item
.
item_id
||
''
,
responsible_department
:
normalizeText
(
item
.
responsible_department
)
||
'未指定责任部门'
,
editor
:
null
,
auditor
:
null
,
}));
}
const
departments
=
uniqueTruthy
(
const
departments
=
uniqueTruthy
(
toArray
(
metadata
.
responsible_department
).
length
>
0
toArray
(
metadata
.
responsible_department
).
length
>
0
?
toArray
(
metadata
.
responsible_department
)
?
toArray
(
metadata
.
responsible_department
)
...
@@ -301,6 +358,54 @@ export function buildDepartmentRectificationItems(record, assignments = [], curr
...
@@ -301,6 +358,54 @@ export function buildDepartmentRectificationItems(record, assignments = [], curr
}));
}));
}
}
export
function
buildDepartmentDelayRequestItems
({
record
,
assignments
=
[],
currentUser
=
null
,
flowRecordId
=
''
,
progressIdEditorByItemId
=
{},
}
=
{})
{
const
metadata
=
record
?.
metadata
||
record
?.
raw
?.
metadata
||
{};
const
departmentItemsById
=
new
Map
(
normalizeDepartmentRectificationItems
(
record
).
map
((
item
)
=>
[
item
.
item_id
,
item
]),
);
const
currentUserId
=
normalizeUserId
(
currentUser
);
return
assignments
.
map
((
assignment
,
index
)
=>
{
const
sourceDepartmentItemId
=
normalizeText
(
assignment
.
source_department_item_id
||
assignment
.
item_id
);
const
sourceDepartmentItem
=
departmentItemsById
.
get
(
sourceDepartmentItemId
);
const
itemId
=
normalizeText
(
assignment
.
item_id
)
||
sourceDepartmentItemId
||
makeDepartmentItemId
(
record
?.
raw
||
record
,
assignment
.
responsible_department
,
index
);
return
{
item_id
:
itemId
,
source_department_item_id
:
sourceDepartmentItemId
,
responsible_department
:
normalizeText
(
assignment
.
responsible_department
)
||
'未指定责任部门'
,
original_due_date
:
sourceDepartmentItem
?.
the_time_of_rectification
||
metadata
.
the_time_of_rectification
||
null
,
requested_due_date
:
null
,
delay_reason
:
''
,
editor
:
normalizeUserId
(
assignment
.
editor
),
auditor
:
normalizeUserId
(
assignment
.
auditor
),
sender
:
currentUserId
,
editor_status
:
EDITOR_STATUS_PENDING
,
auditor_status
:
AUDIT_STATUS_PENDING
,
sender_status
:
AUDIT_STATUS_PENDING
,
progress_id_editor
:
progressIdEditorByItemId
[
itemId
]
||
''
,
progress_id_auditor
:
''
,
progress_id_sender
:
''
,
flow_record_id
:
flowRecordId
,
submitted_at
:
null
,
auditor_decided_at
:
null
,
sender_decided_at
:
null
,
};
});
}
export
function
buildDepartmentParentMetadataPatch
(
items
=
[])
{
export
function
buildDepartmentParentMetadataPatch
(
items
=
[])
{
const
normalizedItems
=
items
.
filter
(
Boolean
);
const
normalizedItems
=
items
.
filter
(
Boolean
);
const
editorIds
=
uniqueTruthy
(
normalizedItems
.
map
((
item
)
=>
item
.
editor
));
const
editorIds
=
uniqueTruthy
(
normalizedItems
.
map
((
item
)
=>
item
.
editor
));
...
@@ -310,20 +415,14 @@ export function buildDepartmentParentMetadataPatch(items = []) {
...
@@ -310,20 +415,14 @@ export function buildDepartmentParentMetadataPatch(items = []) {
[
DEPARTMENT_RECTIFICATION_FIELD
]:
normalizedItems
,
[
DEPARTMENT_RECTIFICATION_FIELD
]:
normalizedItems
,
fill_in_the_people
:
editorIds
,
fill_in_the_people
:
editorIds
,
review_people
:
auditorIds
,
review_people
:
auditorIds
,
rectification_progress
:
summarize
TextStatu
s
(
rectification_progress
:
summarize
DepartmentProgres
s
(
normalizedItems
.
map
((
item
)
=>
item
.
rectification_progress
),
normalizedItems
.
map
((
item
)
=>
item
.
rectification_progress
),
'部分整改'
,
''
,
),
),
audit_status
:
summarize
Tex
tStatus
(
audit_status
:
summarize
DepartmentAudi
tStatus
(
normalizedItems
.
map
((
item
)
=>
item
.
audit_status
),
normalizedItems
.
map
((
item
)
=>
item
.
audit_status
),
'部分审批'
,
AUDIT_STATUS_PENDING
,
),
),
final_audit_status
:
summarize
Tex
tStatus
(
final_audit_status
:
summarize
DepartmentAudi
tStatus
(
normalizedItems
.
map
((
item
)
=>
item
.
final_audit_status
),
normalizedItems
.
map
((
item
)
=>
item
.
final_audit_status
),
'部分审批'
,
AUDIT_STATUS_PENDING
,
),
),
the_time_of_rectification
:
summarizeDate
(
the_time_of_rectification
:
summarizeDate
(
normalizedItems
.
map
((
item
)
=>
item
.
the_time_of_rectification
),
normalizedItems
.
map
((
item
)
=>
item
.
the_time_of_rectification
),
...
@@ -668,25 +767,13 @@ export function normalizeProblemRectificationRecord(record) {
...
@@ -668,25 +767,13 @@ export function normalizeProblemRectificationRecord(record) {
const
departmentItems
=
normalizeDepartmentRectificationItems
(
record
);
const
departmentItems
=
normalizeDepartmentRectificationItems
(
record
);
const
hasDepartmentItems
=
departmentItems
.
length
>
0
;
const
hasDepartmentItems
=
departmentItems
.
length
>
0
;
const
summarizedProgress
=
hasDepartmentItems
const
summarizedProgress
=
hasDepartmentItems
?
summarizeTextStatus
(
?
summarizeDepartmentProgress
(
departmentItems
.
map
((
item
)
=>
item
.
rectification_progress
))
departmentItems
.
map
((
item
)
=>
item
.
rectification_progress
),
'部分整改'
,
''
,
)
:
normalizeText
(
metadata
.
rectification_progress
);
:
normalizeText
(
metadata
.
rectification_progress
);
const
summarizedAuditStatus
=
hasDepartmentItems
const
summarizedAuditStatus
=
hasDepartmentItems
?
summarizeTextStatus
(
?
summarizeDepartmentAuditStatus
(
departmentItems
.
map
((
item
)
=>
item
.
audit_status
))
departmentItems
.
map
((
item
)
=>
item
.
audit_status
),
'部分审批'
,
AUDIT_STATUS_PENDING
,
)
:
normalizeText
(
metadata
.
audit_status
);
:
normalizeText
(
metadata
.
audit_status
);
const
summarizedFinalAuditStatus
=
hasDepartmentItems
const
summarizedFinalAuditStatus
=
hasDepartmentItems
?
summarizeTextStatus
(
?
summarizeDepartmentAuditStatus
(
departmentItems
.
map
((
item
)
=>
item
.
final_audit_status
))
departmentItems
.
map
((
item
)
=>
item
.
final_audit_status
),
'部分审批'
,
AUDIT_STATUS_PENDING
,
)
:
normalizeText
(
metadata
.
final_audit_status
);
:
normalizeText
(
metadata
.
final_audit_status
);
const
summarizedDueDate
=
hasDepartmentItems
const
summarizedDueDate
=
hasDepartmentItems
?
summarizeDate
(
departmentItems
.
map
((
item
)
=>
item
.
the_time_of_rectification
))
?
summarizeDate
(
departmentItems
.
map
((
item
)
=>
item
.
the_time_of_rectification
))
...
@@ -771,6 +858,7 @@ export function normalizeProblemRectificationRecord(record) {
...
@@ -771,6 +858,7 @@ export function normalizeProblemRectificationRecord(record) {
departmentItems
,
departmentItems
,
hasDepartmentItems
,
hasDepartmentItems
,
delayRequest
:
normalizeDelayRequest
(
metadata
[
DELAY_REQUEST_FIELD
]),
delayRequest
:
normalizeDelayRequest
(
metadata
[
DELAY_REQUEST_FIELD
]),
delayRequestItems
:
normalizeDelayRequestItems
(
metadata
[
DELAY_REQUEST_ITEMS_FIELD
]),
isFixed
,
isFixed
,
isLocked
:
metadata
.
is_locked
===
true
,
isLocked
:
metadata
.
is_locked
===
true
,
isOverdue
,
isOverdue
,
...
...
src/services/subjectsDefinition.md
View file @
004e66ec
...
@@ -152,6 +152,7 @@ type Record = {
...
@@ -152,6 +152,7 @@ type Record = {
| 主责部门 |
`primary_responsible_department`
| text |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 主责部门 |
`primary_responsible_department`
| text |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 部门整改明细 |
`department_rectification_items`
| object |
`[]`
| 否 | 是 | 否 | 否 | 否 |
| 部门整改明细 |
`department_rectification_items`
| object |
`[]`
| 否 | 是 | 否 | 否 | 否 |
| 延期申请 |
`problem_rectification_delay_request`
| subject |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 延期申请 |
`problem_rectification_delay_request`
| subject |
`null`
| 否 | 否 | 否 | 否 | 否 |
| 部门延期申请明细 |
`problem_rectification_delay_request_items`
| object |
`[]`
| 否 | 是 | 否 | 否 | 否 |
| 状态锁定 |
`is_locked`
| boolean |
`false`
| 否 | 否 | 否 | 否 | 否 |
| 状态锁定 |
`is_locked`
| boolean |
`false`
| 否 | 否 | 否 | 否 | 否 |
### 3.1.1 select 字段选项
### 3.1.1 select 字段选项
...
@@ -176,8 +177,9 @@ type Record = {
...
@@ -176,8 +177,9 @@ type Record = {
-
新增驾驶舱扩展字段当前在线上 Subject 中大多仍为
`text`
类型,前端工作台按标准值引导录入,用于支持后续严重程度、问题分类、问题原因和整改质效分析
-
新增驾驶舱扩展字段当前在线上 Subject 中大多仍为
`text`
类型,前端工作台按标准值引导录入,用于支持后续严重程度、问题分类、问题原因和整改质效分析
-
其余
`select`
类型的可选值必须以线上 Subject 配置中的
`settings.options`
为准,禁止在页面内硬编码
-
其余
`select`
类型的可选值必须以线上 Subject 配置中的
`settings.options`
为准,禁止在页面内硬编码
-
`problem_discovery_situation`
曾在历史文档和归档对象中出现,但本次主对象字段定义未包含;新页面只应在 Subject View 或线上字段配置存在时展示,不能作为
`problem_rectification`
固定字段依赖
-
`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`
以明细为事实来源,父字段仅做兼容汇总展示
-
`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`
平级;发起延期不要求已有部门整改明细
-
`problem_rectification_delay_request`
为历史问题级单次延期申请嵌套对象,与
`department_rectification_items`
平级;新发起延期默认按部门写入
`problem_rectification_delay_request_items`
-
`problem_rectification_delay_request_items`
为部门级延期申请明细数组;每个责任部门 1 条延期申请,独立保存填写人、一级审批人、最终审批人、申请完成时间、延期事由、状态和待办 ID
-
`is_locked`
为问题整改主记录的状态锁定标记;仅整改进度汇总值为
`已整改`
的记录允许写入
`true`
,锁定后所有业务字段和流程状态均不可修改,只有解锁操作可以将其写回
`false`
-
`is_locked`
为问题整改主记录的状态锁定标记;仅整改进度汇总值为
`已整改`
的记录允许写入
`true`
,锁定后所有业务字段和流程状态均不可修改,只有解锁操作可以将其写回
`false`
-
部门明细的填写人只能编辑自己负责明细的整改业务字段,送审后(
`editor_status = "已完成"`
)不再允许编辑;审批人审批通过后(
`audit_status = "已审批"`
)不再允许编辑,审批驳回后(
`audit_status = "已驳回"`
)审批人可以编辑该明细的整改业务字段,填写人也恢复编辑。审批人恢复的只是业务字段编辑权限,不获得填写人的送审权限。流程推送人可以编辑本次推送关联的父问题记录及全部部门明细整改业务字段。审批状态、待办 ID、明细 ID 等流程控制字段不作为普通表单字段开放
-
部门明细的填写人只能编辑自己负责明细的整改业务字段,送审后(
`editor_status = "已完成"`
)不再允许编辑;审批人审批通过后(
`audit_status = "已审批"`
)不再允许编辑,审批驳回后(
`audit_status = "已驳回"`
)审批人可以编辑该明细的整改业务字段,填写人也恢复编辑。审批人恢复的只是业务字段编辑权限,不获得填写人的送审权限。流程推送人可以编辑本次推送关联的父问题记录及全部部门明细整改业务字段。审批状态、待办 ID、明细 ID 等流程控制字段不作为普通表单字段开放
-
推送人修改父问题记录或部门明细时,不自动重置该明细已经形成的审批状态,也不自动重新生成流程待办
-
推送人修改父问题记录或部门明细时,不自动重置该明细已经形成的审批状态,也不自动重新生成流程待办
...
@@ -204,14 +206,18 @@ type Record = {
...
@@ -204,14 +206,18 @@ type Record = {
| 更新人 |
`updated_by`
| user | 否 | 最近更新用户
`_id`
|
| 更新人 |
`updated_by`
| user | 否 | 最近更新用户
`_id`
|
| 更新时间 |
`updated_at`
| date | 否 | 最近更新时间 |
| 更新时间 |
`updated_at`
| date | 否 | 最近更新时间 |
### 3.1.4 `problem_rectification_delay_request` 嵌套对象
### 3.1.4 `problem_rectification_delay_request`
/ `problem_rectification_delay_request_items`
嵌套对象
-
**subject**
:
`problem_rectification_delay_request`
-
**subject**
:
`problem_rectification_delay_request`
-
**父级路径**
:
`metadata.problem_rectification_delay_request`
-
**父级路径**
:
`metadata.problem_rectification_delay_request`
-
**部门级父级路径**
:
`metadata.problem_rectification_delay_request_items[]`
| 字段标签 | 字段别名 | 字段类型 | 是否必填 | 说明 |
| 字段标签 | 字段别名 | 字段类型 | 是否必填 | 说明 |
| --- | --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| 原预计完成时间 |
`original_due_date`
| date | 否 | 发起申请时从问题主记录
`the_time_of_rectification`
复制,保存 ISO 8601 |
| 明细 ID |
`item_id`
| text | 部门级必填 | 部门延期申请唯一标识,用于行级保存、审批和待办回写 |
| 关联部门整改明细 ID |
`source_department_item_id`
| text | 否 | 有
`department_rectification_items`
时保存对应
`item_id`
,最终审批通过后用于回写该部门预计完成时间 |
| 责任部门 |
`responsible_department`
| text | 部门级必填 | 当前延期申请对应的责任部门 |
| 原预计完成时间 |
`original_due_date`
| date | 否 | 发起申请时优先从对应部门明细
`the_time_of_rectification`
复制,无部门明细时从问题主记录复制,保存 ISO 8601 |
| 申请完成时间 |
`requested_due_date`
| date | 否 | 填写人填写;提交申请时必填并保存 ISO 8601 |
| 申请完成时间 |
`requested_due_date`
| date | 否 | 填写人填写;提交申请时必填并保存 ISO 8601 |
| 延期事由 |
`delay_reason`
| long_text | 否 | 填写人填写;提交申请时必填 |
| 延期事由 |
`delay_reason`
| long_text | 否 | 填写人填写;提交申请时必填 |
| 填写人 |
`editor`
| user | 否 | 保存推送时选择的填写人
`_id`
|
| 填写人 |
`editor`
| user | 否 | 保存推送时选择的填写人
`_id`
|
...
@@ -230,11 +236,11 @@ type Record = {
...
@@ -230,11 +236,11 @@ type Record = {
写入约定:
写入约定:
-
延期申请发起时
只初始化问题主记录的嵌套对象和填写人 OA 待办,不修改主记录
`the_time_of_rectification`
-
延期申请发起时
初始化问题主记录的部门级延期申请数组和填写人 OA 待办,不修改主记录或部门明细的
`the_time_of_rectification`
-
`requested_due_date`
、
`delay_reason`
在保存草稿时可以为空,在提交申请时由前端强制校验必填
-
`requested_due_date`
、
`delay_reason`
在保存草稿时可以为空,在提交申请时由前端强制校验必填
-
一级审批或最终审批驳回后,
`editor_status`
重置为
`未完成`
,并重新创建
填写人 OA 待办
-
一级审批或最终审批驳回后,
仅对应部门延期申请的
`editor_status`
重置为
`未完成`
,并重新创建该部门
填写人 OA 待办
-
只有
`sender_status = "已审批"`
时,才把
`requested_due_date`
写回问题主记录
`the_time_of_rectification`
-
只有
部门延期申请
`sender_status = "已审批"`
时,才把该行
`requested_due_date`
写回对应
`department_rectification_items[].the_time_of_rectification`
;如果不存在对应部门整改明细,则回退
写回问题主记录
`the_time_of_rectification`
-
同一问题主记录已有
该嵌套对象
时,不允许再次创建另一份延期申请
-
同一问题主记录已有
`problem_rectification_delay_request`
或
`problem_rectification_delay_request_items`
时,不允许再次创建另一份延期申请
### 3.1.5 metadata 示例
### 3.1.5 metadata 示例
...
@@ -363,8 +369,8 @@ type Record = {
...
@@ -363,8 +369,8 @@ type Record = {
-
`restriction_value`
保存被推送整改记录的
`_id[]`
-
`restriction_value`
保存被推送整改记录的
`_id[]`
-
`reference_record_id`
与
`restriction_value`
保持一致,作为显式的“关联记录 ID”冗余字段
-
`reference_record_id`
与
`restriction_value`
保持一致,作为显式的“关联记录 ID”冗余字段
-
`subject_name`
保存被推送记录所属对象名,当前整改流程固定为
`problem_rectification`
-
`subject_name`
保存被推送记录所属对象名,当前整改流程固定为
`problem_rectification`
-
`flow_mode`
区分流程:
`department`
表示单条问题按责任部门生成整改明细行,
`batch`
表示多选问题的单填写人 / 单审批人简单推送,
`delay`
表示
问题级延期申请;历史
`delay_department`
值仅保留页面识别兼容
-
`flow_mode`
区分流程:
`department`
表示单条问题按责任部门生成整改明细行,
`batch`
表示多选问题的单填写人 / 单审批人简单推送,
`delay`
表示
历史问题级延期申请,
`delay_department`
表示按责任部门生成延期申请明细
-
`department_item_ids`
保存本次部门流程涉及的
`department_rectification
_items[].item_id`
-
`department_item_ids`
保存本次部门流程涉及的
部门级
`item_id`
;整改流程对应
`department_rectification_items[].item_id`
,延期流程对应
`problem_rectification_delay_request
_items[].item_id`
-
`progress_id_editor`
、
`progress_id_auditor`
、
`progress_id_sender`
用于记录每一步用户确认动作生成的流程 ID,用来区分当前流程推进到了哪一步
-
`progress_id_editor`
、
`progress_id_auditor`
、
`progress_id_sender`
用于记录每一步用户确认动作生成的流程 ID,用来区分当前流程推进到了哪一步
-
`editor_status`
:当前项目统一使用
`未完成`
、
`已完成`
-
`editor_status`
:当前项目统一使用
`未完成`
、
`已完成`
-
`auditor_status`
:当前项目统一使用
`未完成`
、
`已完成`
-
`auditor_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