目录

shuoai-call

前端代码: 1.followup-workspace.tsx ‘use client’;

    setTranscript(session.segments.map((segment) => `${segment.speaker}: ${segment.text}`).join('\n'));
    setCallState(session.state === 'ended' ? 'ended' : 'connected');
    return;
  }
  const config = USE_DIRECT_WEBRTC_DIAL
    ? await createFollowupWebrtcSession(selectedTask.id)
    : await (async () => {
      const startedSession = await startCall(selectedTask.id);
      setActiveSession(startedSession);
      activeSessionIdRef.current = startedSession.id;
      setTranscript(startedSession.segments.map((segment) => `${segment.speaker}: ${segment.text}`).join('\n'));
      if (startedSession.state === 'ended') {
        throw new Error('Follow-up session ended before WebRTC join');
      }
      setCallState('ringing');
      openEventStream(startedSession.id);
      const join = await prepareFollowupWebrtcJoin(startedSession.id);
      return { ...join, session: startedSession };
    })();
  setActiveSession(config.session);
  activeSessionIdRef.current = config.session.id;
  openEventStream(config.session.id);
  const client = webrtcClientRef.current;
  if (!client) throw new Error('WebRTC client is not ready');
  client.setCallListener(handleWebrtcEvent);
  await client.connect({
    extension: config.extension,
    sipUri: config.sipUri,
    websocketUrl: config.websocketUrl,
    authorizationUsername: config.authorizationUsername,
    password: config.password,
  });
  await client.call(config.targetUri, remoteAudioRef.current, [`X-Followup-Session-Id: ${config.session.id}`]);
  const session = await attachFollowupWebrtcCall(config.session.id, { callId: client.getCallId() });
  mergeSession(session);
  setCallState('connected');
} catch (error) {
  // eslint-disable-next-line no-console
  console.error(error);
  setCallState('error');
}

};

const handleHangupCall = async (): Promise => { if (!activeSession) return;

            key={task.id}
            type="button"
      
    </div>
  </header>

  <section className="mx-auto grid max-w-7xl grid-cols-[1fr_360px] gap-4 p-4">
    <div className="overflow-hidden rounded-md border border-slate-200 bg-white">
      <div className="grid grid-cols-[120px_140px_110px_140px_130px_130px_1fr_48px] border-b border-slate-200 bg-slate-50 px-3 py-2 text-xs font-medium text-slate-500">
        <div>患者</div>
        <div>手机号</div>
        <div>来源</div>
        <div>日期</div>
        <div>科室</div>
        <div>随访人</div>
        <div>计划</div>
        <div />
      </div>

      {rows.map((row, index) => (
        <div
          key={index}
          className="grid grid-cols-[120px_140px_110px_140px_130px_130px_1fr_48px] gap-2 border-b border-slate-100 p-3"
        >
          <input
            aria-label={`患者 ${index + 1}`}
            className="rounded-md border border-slate-200 px-2 py-2 text-sm outline-none focus:border-emerald-500"
            value={row.patientName}
            onChange={(event) => updateRow(index, { patientName: event.target.value })}
          />
          <input
            aria-label={`手机号 ${index + 1}`}
            className="rounded-md border border-slate-200 px-2 py-2 text-sm outline-none focus:border-emerald-500"
            value={row.phone}
            onChange={(event) => updateRow(index, { phone: event.target.value })}
          />
          <select
            aria-label={`来源 ${index + 1}`}
            className="rounded-md border border-slate-200 px-2 py-2 text-sm outline-none focus:border-emerald-500"
            value={row.sourceType}
            onChange={(event) => updateRow(index, { sourceType: event.target.value as FollowupImportRow['sourceType'] })}
          >
            <option value="discharge">出院</option>
            <option value="outpatient">门诊</option>
          </select>
          <input
            aria-label={`日期 ${index + 1}`}
            className="rounded-md border border-slate-200 px-2 py-2 text-sm outline-none focus:border-emerald-500"
            type="date"
            value={row.sourceDate}
            onChange={(event) => updateRow(index, { sourceDate: event.target.value })}
          />
          <input
        
<div className="rounded-md border border-slate-200 bg-white px-4 py-3">
  <p className="text-xs font-medium text-slate-500">{label}</p>
  <p className="mt-1 text-2xl font-semibold">{value}</p>
</div>

); }

function Panel({ title, description, children }: { title: string; description: string; children: React.ReactNode }): React.ReactElement { return (

{title}

{description}

{children}
); }

关于

本系统是一个面向医疗机构随访管理场景的智能随访管理系统,围绕随访工作流、医患沟通与数据智能三大核心维度,构建了覆盖随访任务全生命周期管理、批量任务导入、电话外呼与WebRTC实时通话、实时语音转写(ASR)、AI智能摘要生成、短信随访与患者自助填报、随访模板管理、基础数据管理、RBAC权限控制及审计日志等功能的综合性解决方案。

62.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号