shimai
2026-03-09 2cfe2f7e5c51dc4cb2c312bb8acc4d664779005d
refactor:重构状态等逻辑
6 files modified
75 ■■■■ changed files
web-app/src/components/common/OutboundCallWidget.jsx 33 ●●●● patch | view | raw | blame | history
web-app/src/components/dashboard/TabContainer.jsx 2 ●●● patch | view | raw | blame | history
web-app/src/contexts/CaseDataContext.jsx 28 ●●●●● patch | view | raw | blame | history
web-app/src/services/MediationAgreementAPIService.js 2 ●●● patch | view | raw | blame | history
web-app/src/services/OutboundBotAPIService.js 8 ●●●●● patch | view | raw | blame | history
web-app/src/utils/urlParams.js 2 ●●● patch | view | raw | blame | history
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; // 标记为删除
              }
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('协议重新生成成功!');
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,
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 });
  }
}
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;
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',