Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
I
integrity_practice_management_new
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
integrity_practice_management_new
Commits
2ebc3759
Commit
2ebc3759
authored
Sep 30, 2026
by
drigle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 修复自查底稿推送校验与流程链接
parent
46ec095b
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
46 additions
and
9 deletions
+46
-9
.umirc.ts
.umirc.ts
+5
-0
manifest.json
public/manifest.json
+1
-1
test-self-inspection-push.cjs
scripts/test-self-inspection-push.cjs
+2
-0
AppIcons.jsx
src/components/AppIcons.jsx
+2
-0
application.js
src/config/application.js
+10
-1
integrity-practice-management.business-flow.md
...management/integrity-practice-management.business-flow.md
+10
-3
integrityPracticeWorkbenchService.js
..._practice_management/integrityPracticeWorkbenchService.js
+16
-4
No files found.
.umirc.ts
View file @
2ebc3759
...
@@ -34,6 +34,11 @@ export default defineConfig({
...
@@ -34,6 +34,11 @@ export default defineConfig({
'react-dom'
:
resolvePackageRoot
(
'react-dom'
),
'react-dom'
:
resolvePackageRoot
(
'react-dom'
),
},
},
routes
:
[
routes
:
[
{
path
:
'/self_inspection_form'
,
wrappers
:
[
'@/wrapper/Site'
,
'@/wrapper/Auth'
],
component
:
'./integrity_practice_management/SelfInspectionFlowPage'
,
},
{
{
path
:
ROUTE_PATHS
.
login
,
path
:
ROUTE_PATHS
.
login
,
layout
:
false
,
layout
:
false
,
...
...
public/manifest.json
View file @
2ebc3759
{
{
"name"
:
"integrity_practice_management_new"
,
"name"
:
"integrity_practice_management_new"
,
"version"
:
"1.0.
8
"
,
"version"
:
"1.0.
9
"
,
"build"
:
"abc"
,
"build"
:
"abc"
,
"description"
:
"廉洁从业管理"
,
"description"
:
"廉洁从业管理"
,
"date"
:
"2025-07-14 19:27:20"
,
"date"
:
"2025-07-14 19:27:20"
,
...
...
scripts/test-self-inspection-push.cjs
View file @
2ebc3759
...
@@ -29,6 +29,8 @@ const push = records => exportsObject.executeConfiguredAction('integrityRiskMana
...
@@ -29,6 +29,8 @@ const push = records => exportsObject.executeConfiguredAction('integrityRiskMana
await push([{ _id: 'p1', metadata: {} }]);
await push([{ _id: 'p1', metadata: {} }]);
const created = writes.find(([kind]) => kind === 'create')[1];
const created = writes.find(([kind]) => kind === 'create')[1];
assert.equal(JSON.stringify(created.metadata.restriction_value), '["r1","r2"]');
assert.equal(JSON.stringify(created.metadata.restriction_value), '["r1","r2"]');
assert.equal(writes.find(([kind]) => kind === 'oa')[2].returnUrl, '/flow');
assert.match(writes.find(([kind]) => kind === 'notice')[1].content, /\/flow$/);
writes = []; empty = true;
writes = []; empty = true;
await assert.rejects(() => push([{ _id: 'p1' }, { _id: 'p2' }]), /没有关联自查项目/);
await assert.rejects(() => push([{ _id: 'p1' }, { _id: 'p2' }]), /没有关联自查项目/);
assert.equal(writes.length, 0);
assert.equal(writes.length, 0);
...
...
src/components/AppIcons.jsx
View file @
2ebc3759
...
@@ -25,6 +25,7 @@ import PlusOutlined from '@ant-design/icons/PlusOutlined';
...
@@ -25,6 +25,7 @@ import PlusOutlined from '@ant-design/icons/PlusOutlined';
import
WarningOutlined
from
'@ant-design/icons/WarningOutlined'
;
import
WarningOutlined
from
'@ant-design/icons/WarningOutlined'
;
import
MoreOutlined
from
'@ant-design/icons/MoreOutlined'
;
import
MoreOutlined
from
'@ant-design/icons/MoreOutlined'
;
import
ExportOutlined
from
'@ant-design/icons/ExportOutlined'
;
import
ExportOutlined
from
'@ant-design/icons/ExportOutlined'
;
import
InfoCircleOutlined
from
'@ant-design/icons/InfoCircleOutlined'
;
function
iconStyle
(
size
,
style
)
{
function
iconStyle
(
size
,
style
)
{
return
size
===
undefined
?
style
:
{
fontSize
:
size
,
...
style
};
return
size
===
undefined
?
style
:
{
fontSize
:
size
,
...
style
};
...
@@ -48,6 +49,7 @@ function withSize(Icon) {
...
@@ -48,6 +49,7 @@ function withSize(Icon) {
}
}
export
const
AppGrid
=
withSize
(
AppstoreOutlined
);
export
const
AppGrid
=
withSize
(
AppstoreOutlined
);
export
const
Info
=
withSize
(
InfoCircleOutlined
);
export
const
Bell
=
withSize
(
BellOutlined
);
export
const
Bell
=
withSize
(
BellOutlined
);
export
const
Archive
=
withSize
(
ArchiveOutlined
);
export
const
Archive
=
withSize
(
ArchiveOutlined
);
export
const
Calendar
=
withSize
(
CalendarOutlined
);
export
const
Calendar
=
withSize
(
CalendarOutlined
);
...
...
src/config/application.js
View file @
2ebc3759
...
@@ -2,7 +2,16 @@ export const APPLICATION_DISPLAY_NAME = '廉洁从业管理';
...
@@ -2,7 +2,16 @@ export const APPLICATION_DISPLAY_NAME = '廉洁从业管理';
export
const
APPLICATION_NAME
=
'integrity_practice_management'
;
export
const
APPLICATION_NAME
=
'integrity_practice_management'
;
export
const
APPLICATION_ROUTE_NAME
=
APPLICATION_NAME
;
export
const
APPLICATION_ROUTE_NAME
=
APPLICATION_NAME
;
export
const
AUTHORIZATION_APPLICATION_NAME
=
APPLICATION_NAME
;
export
const
AUTHORIZATION_APPLICATION_NAME
=
APPLICATION_NAME
;
export
const
APPLICATION_BASE_PATH
=
`/
${
APPLICATION_NAME
}
/`
;
export
const
APPLICATION_BASE_PATH
=
typeof
INTEGRITY_PRACTICE_APP_BASE_PATH
!==
'undefined'
?
INTEGRITY_PRACTICE_APP_BASE_PATH
:
`/
${
APPLICATION_NAME
}
/`
;
export
const
SELF_INSPECTION_FLOW_PATH
=
'/self_inspection_form'
;
export
function
getSelfInspectionFlowUrl
(
flowName
,
origin
=
window
.
location
.
origin
)
{
const
basePath
=
APPLICATION_BASE_PATH
.
replace
(
/
\/
+$/
,
''
);
return
`
${
origin
}${
basePath
}${
SELF_INSPECTION_FLOW_PATH
}
?id=
${
encodeURIComponent
(
flowName
)}
`
;
}
export
const
ROUTE_TITLES
=
Object
.
freeze
({
export
const
ROUTE_TITLES
=
Object
.
freeze
({
'/self_check_the_results_of_the_working_draft'
:
'自查底稿填写表'
,
'/self_check_the_results_of_the_working_draft'
:
'自查底稿填写表'
,
...
...
src/pages/integrity_practice_management/integrity-practice-management.business-flow.md
View file @
2ebc3759
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
## 1. 模块范围与入口
## 1. 模块范围与入口
-
应用基路径:
`
/integrity_practice_management
/`
-
应用基路径:
`
.umirc.ts`
中的
`APP_BASE_PATH`
,当前为
`/integrity_practice_management_new
/`
-
默认入口:
`/self_check_the_results_of_the_working_draft`
-
默认入口:
`/self_check_the_results_of_the_working_draft`
-
页面菜单与 Subject 动作配置:
`integrityPracticeConfig.js`
-
页面菜单与 Subject 动作配置:
`integrityPracticeConfig.js`
-
页面统一使用鑫元 HeroUI Pro Shell、
`RecordWorkbench`
和
`RecordDetailDrawer`
;Sidebar 为 offcanvas,移动端通过可访问性 Dialog 打开
-
页面统一使用鑫元 HeroUI Pro Shell、
`RecordWorkbench`
和
`RecordDetailDrawer`
;Sidebar 为 offcanvas,移动端通过可访问性 Dialog 打开
...
@@ -72,18 +72,25 @@
...
@@ -72,18 +72,25 @@
入口:自查底稿填写表 -> “推送自查底稿填写表”。
入口:自查底稿填写表 -> “推送自查底稿填写表”。
1.
通过 HeroUI Modal 中的远程 ComboBox 搜索选择填报人和审核人;两组人员都不能为空,只保存用户
`_id[]`
。
1.
通过 HeroUI Modal 中的远程 ComboBox 搜索选择填报人和审核人;两组人员都不能为空,只保存用户
`_id[]`
。
2.
将填报人写入关联
`self_check_the_project_results.metadata.informant`
,同时写入填写表
`metadata.editor`
。
2.
推送前逐条调用
`GET /record/:name`
读取所选底稿完整详情,从
`metadata.project_outcome`
提取并去重结果 ID;全部底稿通过非空校验后才执行写入。
将填报人写入关联
`self_check_the_project_results.metadata.informant`
,同时写入填写表
`metadata.editor`
。
3.
创建
`message_reference_id`
,保存发送人、填报人、审核人、Subject、View、关联记录和限制条件。
3.
创建
`message_reference_id`
,保存发送人、填报人、审核人、Subject、View、关联记录和限制条件。
4.
为每个填报人调用
`oa_notice:createProgress`
创建 OA 待办,并将任务 ID 写入
`metadata.progress_id_editor`
。
4.
为每个填报人调用
`oa_notice:createProgress`
创建 OA 待办,并将任务 ID 写入
`metadata.progress_id_editor`
。
5.
创建并发送站内通知
,流程链接继续使用历史兼容入口
`/self_inspection_form?id=:flowN
ame`
。
5.
创建并发送站内通知
。首次推送及后续审批通知统一使用当前域名、应用部署基路径和兼容流程入口
`/self_inspection_form?id=:flowName`
;当前完整路径为
`/integrity_practice_management_new/self_inspection_form?id=:flowName`
,其中 ID 为流程主单
`n
ame`
。
填写人提交后,在审核人尚未处理前,填写人可在流程页点击“撤回提交”。撤回会将流程主单的
`editor_status`
、
`auditor_status`
重置为“未完成”,并调用
`oa_notice:updateProgressStatus`
将审核人待办标记为已完成;撤回不发送站内通知。审核人已完成审批或驳回后不可撤回。
填写人提交后,在审核人尚未处理前,填写人可在流程页点击“撤回提交”。撤回会将流程主单的
`editor_status`
、
`auditor_status`
重置为“未完成”,并调用
`oa_notice:updateProgressStatus`
将审核人待办标记为已完成;撤回不发送站内通知。审核人已完成审批或驳回后不可撤回。
限制与异常:
限制与异常:
-
未选择记录、填报人或审核人时不创建流程。
-
未选择记录、填报人或审核人时不创建流程。
-
任一所选底稿没有关联自查项目时,整批推送在写入前停止,不创建空流程、待办或通知。
-
任一接口失败时显示错误,不把当前列表直接标记为成功;已经由后端成功创建的数据按历史非事务协议保留。
-
任一接口失败时显示错误,不把当前列表直接标记为成功;已经由后端成功创建的数据按历史非事务协议保留。
### 5.1 流程页路由与链接兼容
-
`SelfInspectionFlowPage.jsx`
作为独立填写与审核流程页,挂载 Site/Auth 登录校验,不增加业务菜单。
-
`/self_inspection_form`
是应用内兼容路由名,不代表旧表单实现;新推送链接必须带当前部署基路径。
-
已经发出的 OA 待办 URL 不会被前端批量改写;旧根路径链接是否继续可用取决于部署侧是否将该路径转发到本应用。
## 6. 归档流程
## 6. 归档流程
### 6.1 自查底稿填写表
### 6.1 自查底稿填写表
...
...
src/pages/integrity_practice_management/integrityPracticeWorkbenchService.js
View file @
2ebc3759
...
@@ -32,6 +32,7 @@ import {
...
@@ -32,6 +32,7 @@ import {
sortRecordsByView
,
sortRecordsByView
,
toArray
,
toArray
,
}
from
'@/utils/subjectView'
;
}
from
'@/utils/subjectView'
;
import
{
getSelfInspectionFlowUrl
}
from
'@/config/application'
;
import
dayjs
from
'dayjs'
;
import
dayjs
from
'dayjs'
;
import
{
saveAs
}
from
'file-saver'
;
import
{
saveAs
}
from
'file-saver'
;
import
JSZip
from
'jszip'
;
import
JSZip
from
'jszip'
;
...
@@ -585,8 +586,19 @@ async function pushSelfInspectionForm(records, userInfo, assignment) {
...
@@ -585,8 +586,19 @@ async function pushSelfInspectionForm(records, userInfo, assignment) {
throw new Error('请同时选择填报人和审核人');
throw new Error('请同时选择填报人和审核人');
}
}
for (const record of records) {
const preparedRecords = [];
const outcomeIds = toArray(record?.metadata?.project_outcome).map((item) => item?._id || item);
for (const selectedRecord of records) {
const record = await loadRecord(selectedRecord.name || selectedRecord._id);
const outcomeIds = [...new Set(toArray(record?.metadata?.project_outcome)
.map((item) => typeof item === 'string' ? item : item?._id)
.filter(Boolean))];
if (!outcomeIds.length) {
throw new Error(`
底稿“
$
{
record
.
title
||
record
.
name
}
”没有关联自查项目,请检查项目结果后再推送。
`);
}
preparedRecords.push({ record, outcomeIds });
}
for (const { record, outcomeIds } of preparedRecords) {
const views = await getSubjectView('self_check_the_project_results');
const views = await getSubjectView('self_check_the_project_results');
await batchUpdateRecords({
await batchUpdateRecords({
subject: 'self_check_the_project_results',
subject: 'self_check_the_project_results',
...
@@ -625,14 +637,14 @@ async function pushSelfInspectionForm(records, userInfo, assignment) {
...
@@ -625,14 +637,14 @@ async function pushSelfInspectionForm(records, userInfo, assignment) {
sendUserId: userInfo?._id,
sendUserId: userInfo?._id,
sendUserName: userInfo?.username,
sendUserName: userInfo?.username,
sendDisplayName: userInfo?.display_name,
sendDisplayName: userInfo?.display_name,
returnUrl:
`
$
{
window
.
location
.
origin
}
/self_inspection_form
?
id=${flowRecord.name}`
,
returnUrl:
getSelfInspectionFlowUrl(flowRecord.name)
,
});
});
progressIds.push(progress?.data?.taskId);
progressIds.push(progress?.data?.taskId);
}
}
await updateRecord(flowRecord._id, { metadata: { progress_id_editor: progressIds } });
await updateRecord(flowRecord._id, { metadata: { progress_id_editor: progressIds } });
const notice = await createNotice({
const notice = await createNotice({
title: `
$
{
dayjs
().
format
(
'YYYY-MM-DD'
)}
填写廉洁从业自查底稿
`,
title: `
$
{
dayjs
().
format
(
'YYYY-MM-DD'
)}
填写廉洁从业自查底稿
`,
content
:
`请点击链接填写自查底稿:
${
window
.
location
.
origin
}
/self_inspection_form?id=
${
flowRecord
.
name
}
`
,
content: `
请点击链接填写自查底稿:
$
{
getSelfInspectionFlowUrl
(
flowRecord
.
name
)
}
`,
type: 'internal',
type: 'internal',
from: userInfo?._id,
from: userInfo?._id,
to: fillers,
to: fillers,
...
...
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