From 2cfe2f7e5c51dc4cb2c312bb8acc4d664779005d Mon Sep 17 00:00:00 2001
From: shimai <shimai@example.com>
Date: Mon, 09 Mar 2026 14:58:05 +0800
Subject: [PATCH] refactor:重构状态等逻辑
---
web-app/src/services/MediationAgreementAPIService.js | 2
web-app/src/utils/urlParams.js | 2
web-app/src/services/OutboundBotAPIService.js | 10 ++++
web-app/src/components/dashboard/TabContainer.jsx | 2
web-app/src/contexts/CaseDataContext.jsx | 28 +++++++++++++
web-app/src/components/common/OutboundCallWidget.jsx | 35 +++++++++++++----
6 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/web-app/src/components/common/OutboundCallWidget.jsx b/web-app/src/components/common/OutboundCallWidget.jsx
index 1a60f0c..c10d531 100644
--- a/web-app/src/components/common/OutboundCallWidget.jsx
+++ b/web-app/src/components/common/OutboundCallWidget.jsx
@@ -6,10 +6,18 @@
const OUTBOUND_JOBS_KEY = 'outbound_call_jobs';
// 活跃状态列表
-const ACTIVE_STATUSES = ['Scheduling', 'InProgress', 'Calling', 'Ringing', 'Answered'];
+const ACTIVE_STATUSES = ['Scheduling', 'Executing', 'Paused', 'Drafted', 'InProgress', 'Calling', 'Ringing', 'Answered'];
// Scheduling 状态 - 此状态变化不需要调用更新API
const SCHEDULING_STATUS = 'Scheduling';
+const BACKEND_STATUSES = ['Scheduling', 'Executing', 'Succeeded', 'Paused', 'Failed', 'Cancelled', 'Drafted'];
+const STATUS_TO_BACKEND = {
+ InProgress: 'Executing',
+ Calling: 'Executing',
+ Ringing: 'Executing',
+ Answered: 'Executing'
+};
+const isActiveStatus = (status) => !status || ACTIVE_STATUSES.includes(status);
/**
* 智能外呼通话显示组件
@@ -139,11 +147,15 @@
const results = await Promise.all(
jobsToUpdate.map(async (job) => {
try {
+ const statusToUpdate = job.backendStatus || job.newStatus;
+ if (!statusToUpdate) {
+ return { success: false, job };
+ }
await OutboundBotAPIService.updateCallStatus({
jobId: job.jobId,
- callStatus: job.newStatus
+ callStatus: statusToUpdate
});
- console.log(`状态更新成功: ${job.jobId} -> ${job.newStatus}`);
+ console.log(`状态更新成功: ${job.jobId} -> ${statusToUpdate}`);
return { success: true, job };
} catch (err) {
console.error(`状态更新失败: ${job.jobId}`, err);
@@ -184,7 +196,7 @@
const now = Date.now();
return jobs.filter(job => {
// 检查是否为活跃状态
- if (ACTIVE_STATUSES.includes(job.callStatus)) {
+ if (isActiveStatus(job.callStatus)) {
// 检查是否超时(2小时)
const elapsed = now - (job.pollStartTime || job.startTime || now);
if (elapsed > 2 * 60 * 60 * 1000) {
@@ -205,7 +217,7 @@
const storedJobs = loadJobsFromStorage();
// 分离成功任务和失败任务
- const successJobs = storedJobs.filter(job => !job.errorCode && ACTIVE_STATUSES.includes(job.callStatus));
+ const successJobs = storedJobs.filter(job => !job.errorCode && isActiveStatus(job.callStatus));
const failedJobs = storedJobs.filter(job => job.errorCode > 0);
if (successJobs.length === 0) {
@@ -234,21 +246,26 @@
if (response?.data) {
const newStatus = response.data.callStatus;
+ if (!newStatus) {
+ return job;
+ }
+ const backendStatus = STATUS_TO_BACKEND[newStatus] || newStatus;
// 如果状态发生变化,更新任务
if (newStatus !== job.callStatus) {
console.log(`任务 ${job.jobId} 状态更新: ${job.callStatus} -> ${newStatus}`);
// 检查是否需要调用后端更新API(排除Scheduling状态)
- if (job.callStatus !== SCHEDULING_STATUS) {
+ if (backendStatus !== SCHEDULING_STATUS && BACKEND_STATUSES.includes(backendStatus)) {
jobsNeedBackendUpdate.push({
...job,
- newStatus
+ newStatus,
+ backendStatus
});
}
// 如果是终态,可以从轮询中移除
- if (!ACTIVE_STATUSES.includes(newStatus)) {
+ if (!isActiveStatus(newStatus)) {
console.log(`任务 ${job.jobId} 达到终态: ${newStatus}`);
return null; // 标记为删除
}
@@ -638,4 +655,4 @@
);
};
-export default OutboundCallWidget;
\ No newline at end of file
+export default OutboundCallWidget;
diff --git a/web-app/src/components/dashboard/TabContainer.jsx b/web-app/src/components/dashboard/TabContainer.jsx
index ed02399..3f5bd66 100644
--- a/web-app/src/components/dashboard/TabContainer.jsx
+++ b/web-app/src/components/dashboard/TabContainer.jsx
@@ -1430,7 +1430,7 @@
if (!caseId) return;
setActionLoading(prev => ({ ...prev, regenerate: true }));
try {
- const response = await MediationAgreementAPIService.generateAgreement(caseId);
+ const response = await MediationAgreementAPIService.regenerateAgreement(caseId);
if (response?.data?.agreeContent) {
setAgreementContent(response.data.agreeContent);
message.success('协议重新生成成功!');
diff --git a/web-app/src/contexts/CaseDataContext.jsx b/web-app/src/contexts/CaseDataContext.jsx
index e860cec..723ed7b 100644
--- a/web-app/src/contexts/CaseDataContext.jsx
+++ b/web-app/src/contexts/CaseDataContext.jsx
@@ -52,7 +52,16 @@
if (!stored) return false;
const jobs = JSON.parse(stored);
- const activeStatuses = ['Scheduling', 'Executing', 'Paused', 'Drafted'];
+ const activeStatuses = [
+ 'Scheduling',
+ 'Executing',
+ 'Paused',
+ 'Drafted',
+ 'InProgress',
+ 'Calling',
+ 'Ringing',
+ 'Answered'
+ ];
// 过滤出活跃状态的任务
const activeJobs = jobs.filter(job => activeStatuses.includes(job.callStatus));
@@ -255,6 +264,23 @@
console.log('Loading case data with params:', params);
+ if (!params.caseId) {
+ setError('caseId缺失');
+ setLoading(false);
+ return;
+ }
+
+ try {
+ await OutboundBotAPIService.syncStatusByCase({ caseId: params.caseId });
+ } catch (syncError) {
+ console.error('同步外呼状态失败:', syncError);
+ }
+ try {
+ await OutboundBotAPIService.backfillConversationByCase({ caseId: params.caseId });
+ } catch (backfillError) {
+ console.error('回补通话记录失败:', backfillError);
+ }
+
// 调用API获取数据
const response = await ProcessAPIService.getCaseProcessInfo(
params.caseId,
diff --git a/web-app/src/services/MediationAgreementAPIService.js b/web-app/src/services/MediationAgreementAPIService.js
index 9303b22..b8bbc02 100644
--- a/web-app/src/services/MediationAgreementAPIService.js
+++ b/web-app/src/services/MediationAgreementAPIService.js
@@ -68,7 +68,7 @@
* @returns {Promise} 重新生成的协议信息(包含新的agreeId和agreeContent)
*/
static regenerateAgreement(caseId) {
- return request.post('/api/v1/medi-agreement/regenerate', { caseId });
+ return request.post('/api/v1/medi-agreement/regenerate', { caseId }, { timeout: 120000 });
}
}
diff --git a/web-app/src/services/OutboundBotAPIService.js b/web-app/src/services/OutboundBotAPIService.js
index daf5fa1..dcc64ca 100644
--- a/web-app/src/services/OutboundBotAPIService.js
+++ b/web-app/src/services/OutboundBotAPIService.js
@@ -60,6 +60,14 @@
static updateCallStatus(data) {
return request.post('/api/v1/outbound-bot/update-status', data);
}
+
+ static syncStatusByCase(data) {
+ return request.post('/api/v1/outbound-bot/sync-status-by-case', data);
+ }
+
+ static backfillConversationByCase(data) {
+ return request.post('/api/v1/outbound-bot/backfill-conversation-by-case', data);
+ }
}
-export default OutboundBotAPIService;
\ No newline at end of file
+export default OutboundBotAPIService;
diff --git a/web-app/src/utils/urlParams.js b/web-app/src/utils/urlParams.js
index 1d424f6..8b9404d 100644
--- a/web-app/src/utils/urlParams.js
+++ b/web-app/src/utils/urlParams.js
@@ -9,7 +9,7 @@
*/
export const getDefaultParams = () => {
return {
- caseId: '202601281644031088',
+ caseId: '202602261114241000',
caseTypeFirst: '24_01-2',
caseType: '24_02-9',
platform_code: 'AI_0001',
--
Gitblit v1.8.0