Update README.md
前端代码: 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 (
{description}
本系统是一个面向医疗机构随访管理场景的智能随访管理系统,围绕随访工作流、医患沟通与数据智能三大核心维度,构建了覆盖随访任务全生命周期管理、批量任务导入、电话外呼与WebRTC实时通话、实时语音转写(ASR)、AI智能摘要生成、短信随访与患者自助填报、随访模板管理、基础数据管理、RBAC权限控制及审计日志等功能的综合性解决方案。
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
shuoai-call
前端代码: 1.followup-workspace.tsx ‘use client’;
};
const handleHangupCall = async (): Promise => { if (!activeSession) return;
); }
function Panel({ title, description, children }: { title: string; description: string; children: React.ReactNode }): React.ReactElement { return (
{title}
{description}