callout-webpage
系统二:智能外呼与协同系统前端(Quasar ^2.32.2 + @quasar/app-vite ^3.8.3 + Vue 3 + TypeScript)。它调用 apps/callout-server,覆盖外呼调度、流程脚本、坐席协同、转人工、 质检闭环与原生「AI 策略中心」(含三栏一体化话术策略工作台、即时仿真拨测、LLM 后端模型配置与用量大盘)。
功能
- AI 策略中心(一级导航
/ai/*):- 话术策略工作台(
ai/strategies.vue):三栏一体化设计(左栏话术大纲树与节点完备度、中栏微拓扑与 Prompt 黄金调优区、右栏常驻StrategyLivePlayground.vue即时拨测与多轮仿真),支持一句话智能生成/优化 Prompt,免存盘验证 Draft,折叠查看完整输入 Prompt、Raw Content 原始输出与<think>思考链。 - 后端模型配置(
ai/models.vue):在线测试 OpenAI 兼容推理后端连通性与探活,动态配置出厂及自定义模型映射。 - AI 用量大盘(
ai/usage.vue):统计各业务域请求量、Token 消耗、平均延迟与 Fallback 兜底率。
- 话术策略工作台(
- 概览仪表盘(
OverviewStatsGrid):活动 / 联系人 / 呼叫尝试数量,以及接通率、完成率、失败率和平均通话时长。 - 活动管理(
CampaignsTablePanel/CampaignFormFields/use-campaign-editor.ts):创建 / 编辑活动,选择一条或多条外呼线路,按businessCategory中文分组选择业务,设置任务并发、重试、工作时段、计划起止窗口、主叫号码,并启动 / 暂停自动调度器;分类只改善选择器展示,任务仍只保存businessCode,不把分类写入 campaign 或 FreeSWITCH 变量。后端缺少分类或返回未知值时降级到“其他/未知”。任务completed在页面显示为“已结束”,表示当前无待调度联系人,不等于所有联系人均接通成功。 - 流程脚本(
FlowScriptsPage):可视化编排话术、变量、节点、NLU 分支、字段抽取和结果归类;活动通过script_id绑定脚本,运行时由callflow-esl的callout-flow-business执行。 - 线路管理(
LinesPage):维护外呼线路、拨号串模板、默认主叫号码和共享线路并发,并支持号码分配模式(一号多并发 / 号码池轮换 / 一号一并发)与线路号码池维护。 - 活动详情(
CampaignDetailPanels):查看单个活动的联系人、呼叫尝试和派发批次;支持导入联系人、手动派发、重试、编辑 / 删除联系人。 - 呼叫明细 / 详情(
CallAttemptsPage/CallDetailsPage):按意向等级 / 分类筛选的分页呼叫尝试列表,以及单次通话详情与录音回放(用/api/media/config下发的 baseUrl 拼接recordingUrl短文件名播放);通话后情绪分析结果通过EmotionAnalysisSummary/EmotionAnalysisDetail以极性 + 分数 + 文本 / 音频原始结论展示。 - 外呼策略:全局 / 任务级禁呼日期、可呼时段、号码规则、频控、重试和并发限制管理。
- 运营监控(
MonitorPage):实时并发、调度批次、卡住联系人、近 1 分钟提交 / 失败与运行事件告警(SSE)。 - 转人工会议监控(
ConferenceSessionsPanel/ConferenceSessionDetailDialog):查看进行中的转人工会议及成员腿,支持盲转 / 协商转目标坐席、主管监听 / 插话、移除成员,并显示 FreeSWITCH 实时成员数与在会状态。 - 坐席工作台(
AgentWorkspacePage):统一展示示闲 / 忙碌 / 离线三态;普通坐席仅能修改本人状态,主管和管理员可修改全部坐席。工作台与顶部菜单仅提供手动示闲、离线;示闲要求电话已注册,忙碌由系统在转人工预占时设置,振铃与通话期间禁止手动切换,结束后自动示闲(仍有活动转接腿时继续忙碌)。两处通过 SSE 同步状态,忙碌时提示“呼叫占用中,结束后自动示闲”;只有启用、示闲且符合分机注册与 Cell 条件的坐席参与转人工分配。接口约束见 坐席 API。 - 合规与数据(
ComplianceDataPage):DNC 免打扰名单管理。 - 号码导入:向非运行中任务粘贴号码,或同步导入最大 5 MiB、最多 1,000 行的 CSV/TSV,并即时展示逐行错误。
- 系统管理(
SystemAdminPage):用户与角色、操作审计。 - 登录与鉴权:登录页使用独立
AuthLayout(无侧边栏);callout-server下发的permissions决定侧边栏、路由与按钮的可见性(@/stores/auth.ts的can()),未授权访问跳转/403,未登录跳转/login。 - 统一日期时间选择器(
DateTimePickerInput,基于@vuepic/vue-datepicker,由@/boot/vue-datepicker.ts注册):贯穿活动计划窗口(datetime)与工作时段(time)、策略可呼时段、坐席回访时间、合规等所有日期 / 时间 / 时段输入。支持手动输入 + 掩码 + 合法性校验,并提供日历 / 时间面板选择(datetime/datetime-local-minute/date/time四种模式)。
手动派发批次大小只是一次提交请求的期望数量。实际提交数量仍会同时受所选活动剩余并发槽位和绑定线路池剩余共享槽位限制。
开发
bash
bun install # 或:npm install
bun run dev # quasar dev — http://localhost:19920
bun run build # quasar build → dist/spa
bun run test # Bun 单元测试
bun run lint # oxfmt + oxlint --fix
bun run typecheck # vue-tsc --noEmit源码结构
src/pages/:文件路由页面和页面级业务编排。src/components/:可复用展示与交互组件(含components/flow-scripts/流程画布、节点配置抽屉与编辑器纯模型);来电弹窗、通话台分区和会议详情均不直接访问后端。src/composables/:跨组件状态与业务控制器,包括共享 SIP 实例、活动编辑器、导入和离页保护。src/api/:后端契约和 HTTP/SSE 边界。request.ts只管 API 根地址、Token、{ code, data, msg }信封解包和下载(泛型默认收紧为unknown),types.ts保存 callout-server 公共响应类型,其余文件按领域拆分(campaigns.ts/calls.ts/monitoring.ts/softphone.ts/ai.ts等),全部对齐后端扁平化动作语义 RPC 规范。src/services/:需要跨组件缓存、定时刷新的无状态服务层,当前只有软电话 ICE 凭据缓存(softphone-ice-config.ts,到期前 5 分钟自动续期)。src/stores/:基于 Pinia 的登录态与权限(auth.ts)、全局参考数据(callout-reference.ts)及当前坐席状态。src/router/:文件路由入口(index.ts)与动态菜单/鉴权跳转路由构建(auth-routing.ts)。src/types/、src/utils/:无组件生命周期依赖的 UI 类型与纯函数,优先通过 Bun 单元测试覆盖。
流程编辑器使用 flow-editor-types.ts 统一页面与属性面板的视图模型,并通过 flow-editor-model.ts 对历史脚本或外部 JSON 做运行时收窄。浏览器软电话遵循 “SIP 状态、全局编排、来电展示”分层;刷新/关闭保护由单一全局监听器汇总所有活跃 会话,避免软电话总览页为每张坐席卡片重复注册浏览器事件。
开发服务器端口是 19920(quasar.config.ts → devServer.port)。路由使用 history 模式(quasar.config.ts → build.vueRouterMode: "history"),并已启用 filenameBasedRouting:
- 路由文件入口保留在
src/router/index.ts,鉴权守卫和/ -> /overview跳转仍在这里维护。 - 实际页面路由来自
src/pages/目录结构,不再维护src/router/routes.ts。 - 源码 import 统一使用
@/,不再使用src/、components/、stores/等旧别名。
配置
| 环境变量 | 默认值 | 用途 |
|---|---|---|
VITE_CALLOUT_API_BASE_URL | /api | callout-server API 根地址;值会在 Quasar/Vite 构建期固化 |
VITE_SOFTPHONE_SERVICE_NUMBER | 5020 | 坐席通话台默认拨打的业务号;页面输入框可临时覆盖 |
自定义 env 类型定义在项目根目录 env.d.ts。@/api/request.ts 只负责鉴权、 { code, data, msg } 信封、下载和请求错误;调用方直接从 @/api/auth、 @/api/campaigns、@/api/calls、@/api/media 等对应领域文件引入接口, 公共契约统一从 @/api/types 引入。项目不提供聚合所有接口的 barrel 模块。
API 根地址由 VITE_CALLOUT_API_BASE_URL 在构建期注入,未设置或为空时使用同域 /api。 配置值推荐明确包含 /api;未包含时请求层会自动补齐,并清理首尾空白和末尾斜杠。 普通请求、文件上传下载、SSE 和 EventSource 均通过该 API 根地址访问。
默认部署方式是在托管该前端的站点上将同域 /api 反向代理到 callout-server (默认 http://127.0.0.1:9920),并保留上游请求中的 /api 路径。使用自定义代理前缀 或浏览器可访问的后端地址时,在构建前设置变量,例如:
bash
VITE_CALLOUT_API_BASE_URL=/gateway/callout/api bun run build执行构建后,产物位于 dist/spa/。API 根地址变化后必须重新构建前端。使用默认 /api 时,开发服务器会将其代理到 http://localhost:9920。
浏览器软电话的分机、密码、Realm 与 WS/WSS 地址全部取坐席配置;业务号默认取 VITE_SOFTPHONE_SERVICE_NUMBER,坐席可在通话台手动改写本次呼叫目标。
这些默认值现在集中维护在 quasar.config.ts,避免 README、类型注释和页面源码各自维护不同口径。