feat: systematic functional audit — fix 18 issues across Phase A/B

Phase A (P1 production blockers):
- A1: Apply IP rate limiting to public routes (login/refresh)
- A2: Publish domain events for workflow instance state transitions
  (completed/suspended/resumed/terminated) via outbox pattern
- A3: Replace hardcoded nil UUID default tenant with dynamic DB lookup
- A4: Add GET /api/v1/audit-logs query endpoint with pagination
- A5: Enhance CORS wildcard warning for production environments

Phase B (P2 functional gaps):
- B1: Remove dead erp-common crate (zero references in codebase)
- B2: Refactor 5 settings pages to use typed API modules instead of
  direct client calls; create api/themes.ts; delete dead errors.ts
- B3: Add resume/suspend buttons to InstanceMonitor page
- B4: Remove unused EventHandler trait from erp-core
- B5: Handle task.completed events in message module (send notifications)
- B6: Wire TimeoutChecker as 60s background task
- B7: Auto-skip ServiceTask nodes instead of crashing the process
- B8: Remove empty register_routes() from ErpModule trait and modules
This commit is contained in:
iven
2026-04-12 15:22:28 +08:00
parent 685df5e458
commit 14f431efff
34 changed files with 785 additions and 304 deletions

View File

@@ -13,22 +13,20 @@ import {
Typography,
} from 'antd';
import { PlusOutlined, NumberOutlined } from '@ant-design/icons';
import client from '../../api/client';
import {
listNumberingRules,
createNumberingRule,
updateNumberingRule,
deleteNumberingRule,
generateNumber,
type NumberingRuleInfo,
type CreateNumberingRuleRequest,
type UpdateNumberingRuleRequest,
} from '../../api/numberingRules';
// --- Types ---
interface NumberingRule {
id: string;
name: string;
code: string;
prefix?: string;
date_format?: string;
seq_length: number;
seq_start: number;
current_value: number;
separator?: string;
reset_cycle: 'never' | 'daily' | 'monthly' | 'yearly';
}
type NumberingRule = NumberingRuleInfo;
// --- Constants ---
@@ -58,8 +56,8 @@ export default function NumberingRules() {
const fetchRules = useCallback(async () => {
setLoading(true);
try {
const { data: resp } = await client.get('/config/numbering-rules');
setRules(resp.data ?? resp);
const result = await listNumberingRules();
setRules(Array.isArray(result) ? result : result.items ?? []);
} catch {
message.error('加载编号规则失败');
}
@@ -70,22 +68,13 @@ export default function NumberingRules() {
fetchRules();
}, [fetchRules]);
const handleSubmit = async (values: {
name: string;
code: string;
prefix?: string;
date_format?: string;
seq_length: number;
seq_start: number;
separator?: string;
reset_cycle: 'never' | 'daily' | 'monthly' | 'yearly';
}) => {
const handleSubmit = async (values: CreateNumberingRuleRequest) => {
try {
if (editRule) {
await client.put(`/config/numbering-rules/${editRule.id}`, values);
await updateNumberingRule(editRule.id, values as UpdateNumberingRuleRequest);
message.success('编号规则更新成功');
} else {
await client.post('/config/numbering-rules', values);
await createNumberingRule(values);
message.success('编号规则创建成功');
}
closeModal();
@@ -100,7 +89,7 @@ export default function NumberingRules() {
const handleDelete = async (id: string) => {
try {
await client.delete(`/config/numbering-rules/${id}`);
await deleteNumberingRule(id);
message.success('编号规则已删除');
fetchRules();
} catch {
@@ -110,11 +99,8 @@ export default function NumberingRules() {
const handleGenerate = async (rule: NumberingRule) => {
try {
const { data: resp } = await client.post(
`/config/numbering-rules/${rule.id}/generate`,
);
const generated = resp.data?.number ?? resp.data ?? resp.number ?? resp;
message.success(`生成编号: ${generated}`);
const result = await generateNumber(rule.id);
message.success(`生成编号: ${result.number}`);
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data