Commit 8bb072d7 authored by David Yang's avatar David Yang

feat: improve problem rectification workflow ui

parent 78c9be51
......@@ -376,22 +376,6 @@ export default function ProblemRectificationLayout() {
<div className="text-sm text-zinc-500">{currentGroupTitle}</div>
</div>
<div className="mb-4 rounded-3xl border border-white/80 bg-white/75 px-5 py-4 shadow-sm backdrop-blur">
<div className="flex flex-wrap items-center justify-between gap-3">
<div>
<div className="text-xs font-semibold uppercase tracking-[0.24em] text-rose-500">
Problem Rectification
</div>
<div className="mt-1 text-xl font-semibold text-slate-900">
问题整改模块重构
</div>
</div>
<div className="text-sm text-slate-500">
先保证业务流转通顺,再逐步补齐细节体验。
</div>
</div>
</div>
<div className="flex-1 overflow-y-auto rounded-[28px] border border-white/80 bg-white/80 p-4 shadow-sm backdrop-blur sm:p-6">
<Outlet />
</div>
......
......@@ -225,8 +225,12 @@
- `auditor`
- `restriction_key = "_id"`
- `restriction_value = 选中问题记录 ID 列表`
- `reference_record_id = 选中问题记录 ID 列表`
- `subject_name = "problem_rectification"`
- `view_name = 当前筛选视图名`
- `editor_status = "未完成"`
- `auditor_status = "未完成"`
- `sender_status = "未完成"`
5. 批量更新选中问题的 `metadata.fill_in_the_people`
6. 发送内部通知与 OA 待办
......@@ -271,11 +275,12 @@
- 批量更新所有关联问题 `metadata.audit_status = "已审批"`
- 回写 `metadata.review_people`
- 创建最终审核待办给发起人
- 更新流程主单 `auditor_status = "已完成"`、`sender_status = "未审批"`
- 更新流程主单 `auditor_status = "已完成"`、`sender_status = "未完成"`
2. 驳回
- 批量更新所有关联问题 `metadata.audit_status = "已驳回"`
- 重新给填报人发通知和待办
- 更新流程主单 `editor_status = "未完成"`、`auditor_status = "已完成"`
- 重新写入 `progress_id_editor`,使流程回到填写阶段
推荐新交互:
......@@ -294,6 +299,7 @@
- 批量更新所有关联问题 `metadata.final_audit_status = "已驳回"`
- 重建填写人待办
- 更新流程主单 `editor_status = "未完成"`、`sender_status = "已完成"`
- 重新写入 `progress_id_editor`,使流程重新回到填写阶段
推荐新交互:
......@@ -323,13 +329,21 @@
### 8.2 流程主单状态字段
`message_reference_id` 中旧代码已使用:
`message_reference_id` 在当前项目中的约定:
- `sender` 记录推送发起人
- `editor` 记录填写人列表
- `auditor` 记录审核人列表
- `restriction_key` 默认固定为 `_id`
- `restriction_value` 保存本次推送绑定的整改记录 `_id[]`
- `reference_record_id` 作为关联记录 ID 冗余字段,和 `restriction_value` 一致
- `subject_name` 保存被推送记录的对象名,当前为 `problem_rectification`
- `progress_id_editor`、`progress_id_auditor`、`progress_id_sender` 记录每一步用户确认行为对应的流程 ID
- `editor_status`:`未完成`、`已完成`
- `auditor_status`:`未审批`、`已完成`
- `sender_status`:`未审批`、`已完成`、`已驳回`
- `auditor_status`:`未完成`、`已完成`
- `sender_status`:`未完成`、`已完成`
新项目可以继续兼容这些值,但 UI 层建议用更清晰的步骤条或状态标签展示,而不是直接暴露原字段名。
当前新页面不再依赖旧版 `未审批`、`已驳回` 之类流程主单状态,而是通过“状态字段 + 当前 progress_id”共同判断流程走向。驳回场景通过重建 `progress_id_editor` 并将 `editor_status` 重置为 `未完成` 来回到填写阶段。
---
......@@ -649,6 +663,7 @@ const result = await queryUsers(0, 20, {
- 功能入口
- 关键交互步骤
- 推送、填报、复核、最终审核流程
- `message_reference_id` 的当前字段协议与回流规则
- 驾驶舱统计口径
- 归档流程
- 状态变化与数据约束
......
......@@ -4,6 +4,7 @@ import {
loadSubject,
queryRecords,
} from '@/services/DataService';
import { DEPARTMENT_GROUPS } from './problemRectificationDashboardService';
import {
buildViewColumns,
emptyValueForField,
......@@ -60,16 +61,25 @@ function formatDateText(value) {
export function normalizeProblemRectificationRecord(record) {
const metadata = record?.metadata || {};
const dueDate = metadata.the_time_of_rectification
? dayjs(metadata.the_time_of_rectification)
: null;
return {
id: record?._id || record?.name || '',
name: record?.name || '',
title: normalizeText(record?.title) || normalizeText(metadata.project_name),
projectName: normalizeText(metadata.project_name) || '-',
inspectUnit: normalizeText(metadata.inspect_the_implementing_unit),
progress: normalizeText(metadata.rectification_progress),
feedbackUnit: normalizeText(metadata.feedback_unit),
auditStatus: normalizeText(metadata.audit_status),
finalAuditStatus: normalizeText(metadata.final_audit_status),
problemType: normalizeText(metadata.problem_type),
problemFrom: normalizeText(metadata.problem_from),
relatedIssueDomain: normalizeText(metadata.related_issue_domain),
brief: normalizeText(metadata.problem_brief),
dueDate: dueDate && dueDate.isValid() ? dueDate : null,
fillUsers: toArray(metadata.fill_in_the_people)
.map(normalizeUserLabel)
.filter(Boolean),
......@@ -190,6 +200,90 @@ export function buildProblemRectificationConfiguredListView(records, filters, gr
};
}
function matchesDepartmentGroup(record, groupKey) {
if (!groupKey || groupKey === 'all') {
return true;
}
const matchedGroup = DEPARTMENT_GROUPS.find((group) => group.key === groupKey);
if (!matchedGroup) {
return true;
}
if (!matchedGroup.matchFeedbackUnits || matchedGroup.matchFeedbackUnits.length === 0) {
return true;
}
return matchedGroup.matchFeedbackUnits.includes(record.feedbackUnit);
}
function buildSearchText(record) {
return [
record.projectName,
record.inspectUnit,
record.feedbackUnit,
record.progress,
record.auditStatus,
record.finalAuditStatus,
record.problemType,
record.problemFrom,
record.relatedIssueDomain,
record.brief,
record.dueDateLabel,
record.fillUsers.join(' '),
record.reviewUsers.join(' '),
]
.map((value) => normalizeText(value))
.filter(Boolean)
.join(' ')
.toLowerCase();
}
export function buildProblemRectificationListView(records = [], filters = {}) {
const keyword = normalizeText(filters.keyword).toLowerCase();
const progress = normalizeText(filters.progress);
const auditStatus = normalizeText(filters.auditStatus);
const groupKey = normalizeText(filters.groupKey) || 'all';
const scopedRecords = records.filter((record) => {
if (progress && record.progress !== progress) {
return false;
}
if (auditStatus && record.auditStatus !== auditStatus) {
return false;
}
if (keyword && !buildSearchText(record).includes(keyword)) {
return false;
}
return true;
});
const groupCounts = Object.fromEntries(
DEPARTMENT_GROUPS.map((group) => [
group.key,
scopedRecords.filter((record) => matchesDepartmentGroup(record, group.key)).length,
]),
);
const filteredRecords = scopedRecords.filter((record) =>
matchesDepartmentGroup(record, groupKey),
);
return {
filteredRecords,
groupCounts,
progressOptions: Array.from(
new Set(records.map((item) => item.progress).filter(Boolean)),
),
auditStatusOptions: Array.from(
new Set(records.map((item) => item.auditStatus).filter(Boolean)),
),
};
}
export function buildProblemRectificationCreateFormFields(gridView, subject) {
const columns = buildViewColumnsForList(gridView, subject)
.filter((column) => column.field !== 'title')
......
......@@ -239,25 +239,32 @@ type Record = {
| 字段标签 | 字段别名 | 字段类型 | 是否主键 | 是否多值 | 是否必填 |
| --- | --- | --- | --- | --- | --- |
| 发起人 | `sender` | user | 否 | 否 | 是 |
| 填写人 | `editor` | user | 否 | 是 | 是 |
| 审核人 | `auditor` | user | 否 | 是 | 是 |
| 限制字段 | `restriction_key` | text | 否 | 否 | 是 |
| 限制值列表 | `restriction_value` | text | 否 | 是 | 是 |
| 发送人 | `sender` | user | 否 | 否 | 否 |
| 填写人 | `editor` | user | 否 | 是 | 否 |
| 审核人 | `auditor` | user | 否 | 是 | 否 |
| 约束 key | `restriction_key` | text | 否 | 否 | 否 |
| 约束值 | `restriction_value` | text | 否 | 是 | 否 |
| 对象名 | `subject_name` | text | 否 | 否 | 否 |
| 视图名称 | `view_name` | text | 否 | 否 | 否 |
| 主题名称 | `subject_name` | text | 否 | 否 | 是 |
| 关联记录 ID | `reference_record_id` | text | 否 | 是 | 否 |
| 填写待办 ID | `progress_id_editor` | text | 否 | 是 | 否 |
| 审核待办 ID | `progress_id_auditor` | text | 否 | 是 | 否 |
| 最终审核待办 ID | `progress_id_sender` | text | 否 | 否 | 否 |
| 填写状态 | `editor_status` | select | 否 | 否 | 否 |
| 审核状态 | `auditor_status` | select | 否 | 否 | 否 |
| 发起人状态 | `sender_status` | select | 否 | 否 | 否 |
### 3.4.1 旧流程状态值
- `editor_status`:旧页面使用过 `未完成`、`已完成`
- `auditor_status`:旧页面使用过 `未审批`、`已完成`
- `sender_status`:旧页面使用过 `未审批`、`已完成`、`已驳回`
| 发送人状态 | `sender_status` | select | 否 | 否 | 否 |
### 3.4.1 当前流程写入约定
- `restriction_key` 默认写 `_id`
- `restriction_value` 保存被推送整改记录的 `_id[]`
- `reference_record_id` 与 `restriction_value` 保持一致,作为显式的“关联记录 ID”冗余字段
- `subject_name` 保存被推送记录所属对象名,当前整改流程固定为 `problem_rectification`
- `progress_id_editor`、`progress_id_auditor`、`progress_id_sender` 用于记录每一步用户确认动作生成的流程 ID,用来区分当前流程推进到了哪一步
- `editor_status`:当前项目统一使用 `未完成`、`已完成`
- `auditor_status`:当前项目统一使用 `未完成`、`已完成`
- `sender_status`:当前项目统一使用 `未完成`、`已完成`
- 当复核或最终审核驳回时,流程主单会回写新的 `progress_id_editor`,并将 `editor_status` 重置为 `未完成`,从而重新进入填写阶段
## 3.5 项目管理
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment