13 KiB
使用说明 · 在其它 Vue 项目中引入
本组件库只对外暴露一个组件 ParallelAgentsPanel(其余 MessageBubble / MessageStepsCard /
ParallelSeatStrip / Avatar / MarkdownContent 都是它的内部子组件,无需也不要单独引入)。
宿主只管把它放进自己的页面 / 抽屉 / 弹窗,并传几个 prop。
一、要引入的东西(就这两样)
- 组件:
ParallelAgentsPanel - 样式:
parallel-agents-vue/style.css(一次性引入即可,样式作用域全在.parallel-agents下)
依赖说明:
vue ^3.4(宿主提供,库不打包 vue);markdown-it已打进库内,无需宿主安装。
二、两种引入方式
方式 A:构建成库后按包引入(推荐)
- 在本项目构建:
pnpm install pnpm build:lib # 产出 dist/parallel-agents-vue.{js,umd.cjs,css} - 宿主项目里安装(任选其一):
- 把本目录作为本地依赖:
"parallel-agents-vue": "file:../parallel-agents-vue"; - 或发到你们的私有 npm 后正常
pnpm add parallel-agents-vue。
- 把本目录作为本地依赖:
- 代码里引入:
import { ParallelAgentsPanel } from "parallel-agents-vue"; import "parallel-agents-vue/style.css";
方式 B:直接拷贝源码(无需发包)
把本项目 src/ 下这些拷进宿主项目(保持相对结构),按相对路径引入 ParallelAgentsPanel.vue +
styles/parallel-agents.css 即可:
src/
components/ ParallelAgentsPanel.vue · MessageBubble.vue · MessageStepsCard.vue
ParallelSeatStrip.vue · Avatar.vue · MarkdownContent.vue
composables/ useParallelRun.ts
lib/ avatar-constants.ts
styles/ parallel-agents.css
api.ts · config.ts · types.ts
宿主需有 markdown-it 依赖(pnpm add markdown-it),并保证构建支持 .vue(Vite/@vitejs/plugin-vue)。
三、注册与使用
局部引入(推荐)
<script setup lang="ts">
import { ParallelAgentsPanel } from "parallel-agents-vue";
import "parallel-agents-vue/style.css";
const agents = [
{ agent_id: "roundtable-solution-design", name: "方案设计" },
{ agent_id: "roundtable-risk-review", name: "风险审查" },
];
</script>
<template>
<div style="height: 80vh">
<ParallelAgentsPanel :username="'demo'" :agents="agents" />
</div>
</template>
全局注册(可选)
import ParallelAgentsVue from "parallel-agents-vue";
import "parallel-agents-vue/style.css";
app.use(ParallelAgentsVue); // 之后任意模板可直接用 <ParallelAgentsPanel/>
四、放进抽屉 / 弹窗
组件根元素是 h-full w-full flex flex-col min-h-0,会充满父容器。所以父容器要给一个高度
(弹窗/抽屉本身有高度即可):
<YourDrawer v-model="open" size="large">
<div style="height: 86vh">
<ParallelAgentsPanel :username="currentUsername" :agents="agents" @saved="onSaved" />
</div>
</YourDrawer>
五、接口地址与登录
- 接口地址:默认读
src/config.ts的DEFAULT_BASE_URL(可改源码,或 dev 设VITE_PA_BASE_URL); 也可用:base-urlprop 临时覆盖。 - 登录:把宿主的用户名用
:username传进来即可——组件自动走本面板专用的「绕过常规登录」 公共端点POST /api/parallel-agents/auth/token换 token、缓存、401 自动重登。宿主不用管 token。 若已有 token,可改传:token/:get-token(优先级更高)。- 为什么专用端点:内网部署对标准
/api/v1/auth/login/username有额外限制(口令门/网关裁剪等),拿不到 token;该端点传用户名直接签发(账号不存在自动注册),已在 auth/csrf 中间件白名单里放行。
- 为什么专用端点:内网部署对标准
- token 缓存按
baseUrl::username维度,多个实例/多用户互不串。
六、Props
| prop | 类型 | 必填 | 说明 |
|---|---|---|---|
agents |
{ agent_id, name, avatarType? }[] |
✔ | 要并行调用的智能体(agent_id 必须是真实 id) |
username |
string |
免密自动登录用户名(推荐方式) | |
baseUrl |
string |
后端地址;不传用 config.ts 默认 |
|
token |
string |
已有 Bearer token(优先于 username) | |
getToken |
() => string | Promise<string> |
动态取 token | |
loginPassword |
string |
仅当后端开启口令门时需要 | |
taskId |
string |
传入则挂载时自动加载并回显该任务 | |
model |
string |
可选模型名(不传走默认 / 后端回退) | |
dark |
boolean(默认 true) |
深色面板(自带成色,不依赖宿主主题) |
AgentInput/SavedTask/AgentResult 等类型也从包里导出:
import type { AgentInput, SavedTask, AgentResult } from "parallel-agents-vue"。
六·一、每个参数怎么传(逐个举例)
agents(必填)——「智能体参数」怎么传
一个数组,每项 { agent_id, name?, avatarType? }:
const agents = [
{ agent_id: "roundtable-solution-design", name: "方案设计" }, // 最常用:id + 显示名
{ agent_id: "roundtable-risk-review", name: "风险审查", avatarType: "amber" }, // 顺带指定头像配色
{ agent_id: "demo-expert" }, // 只给 id(显示名回退成 id)
];
<ParallelAgentsPanel :agents="agents" :username="'demo'" />
agent_id必须是后端真实注册的 id(只写名字无效);可用 id 见 06-可用智能体清单.md。name:席位/气泡显示名,可省(省了用 id)。avatarType:可选blue|purple|emerald|amber|pink|human;不传按顺序自动轮转配色。
username——免密登录(推荐)
<ParallelAgentsPanel :username="currentUser.name" :agents="agents" />
baseUrl——后端地址(不传用 config 默认)
<ParallelAgentsPanel :base-url="'http://10.0.0.5:8001'" :username="'demo'" :agents="agents" />
token / getToken——已有登录态时(优先于 username)
<!-- 直接给字符串 token -->
<ParallelAgentsPanel :token="hostToken" :agents="agents" />
<!-- 或给一个(异步)取 token 的函数 -->
<ParallelAgentsPanel :get-token="() => authStore.getAccessToken()" :agents="agents" />
model——指定模型(不传走默认/后端回退;也可在面板右上角下拉切)
<ParallelAgentsPanel :model="'deepseek-chat'" :username="'demo'" :agents="agents" />
dark——深色(默认 true,自带成色)
<ParallelAgentsPanel :dark="true" :username="'demo'" :agents="agents" />
taskId——存储主键 + 回显(见 §七·二)
<ParallelAgentsPanel
:task-id="taskId"
:username="'demo'"
:agents="agents"
@update:taskId="(id) => (taskId = id)"
/>
全量示例(所有参数一起)
<script setup lang="ts">
import { ref } from "vue";
import { ParallelAgentsPanel } from "parallel-agents-vue";
import "parallel-agents-vue/style.css";
import type { AgentInput, AgentResult, SavedTask } from "parallel-agents-vue";
const agents: AgentInput[] = [
{ agent_id: "roundtable-solution-design", name: "方案设计" },
{ agent_id: "roundtable-risk-review", name: "风险审查" },
];
const taskId = ref("task-001");
function onSaved(t: SavedTask) {
console.log("已保存", t.id);
}
function onCompleted(results: AgentResult[]) {
console.log("各智能体返回内容", results);
}
</script>
<template>
<div style="height: 86vh">
<ParallelAgentsPanel
:base-url="'http://localhost:8001'"
:username="'demo'"
:agents="agents"
:task-id="taskId"
:model="'deepseek-chat'"
:dark="true"
@saved="onSaved"
@update:taskId="(id) => (taskId = id)"
@completed="onCompleted"
/>
</div>
</template>
七、事件
| 事件 | 载荷 | 触发时机 |
|---|---|---|
saved |
SavedTask |
保存成功(新建或更新)后 |
update:taskId |
string |
当前任务 id 变化(保存 / 加载历史时) |
completed |
AgentResult[] |
一轮并行分析结束时,回传各智能体返回内容 |
<ParallelAgentsPanel
:username="user"
:agents="agents"
:task-id="taskId"
@saved="(t) => console.log('saved', t.id)"
@update:taskId="(id) => (taskId = id)"
@completed="(results) => console.log('各智能体返回:', results)"
/>
七·一、如何获取模型返回的内容
每个智能体(模型)返回的正文是 AgentResult.content。两种方式,任选其一:
A. 事件:监听 @completed,一轮分析结束时自动回传 AgentResult[]:
<ParallelAgentsPanel
:username="'demo'"
:agents="agents"
@completed="(results) => {
// results: [{ agent_id, name, content, status }]
for (const r of results) console.log(r.name, '→', r.content);
}"
/>
B. 方法(模板 ref):随时主动取(不必等事件):
<script setup lang="ts">
import { ref } from "vue";
import { ParallelAgentsPanel } from "parallel-agents-vue";
import type { AgentResult } from "parallel-agents-vue";
const panelRef = ref<InstanceType<typeof ParallelAgentsPanel> | null>(null);
function readAll() {
const all: AgentResult[] = panelRef.value!.getResults();
// [{ agent_id, name, content, status }]
}
function readOne(id: string) {
const one = panelRef.value!.getResult(id); // AgentResult | null
}
</script>
<template>
<ParallelAgentsPanel ref="panelRef" :username="user" :agents="agents" />
</template>
AgentResult = { agent_id, name, content, status },content 即该智能体模型返回的正文(Markdown)。
defineExpose 还暴露了 start() / cancel(),可由宿主代替按钮触发开始 / 停止。
七·二、如何保存 + 回显聊天记录
保存:面板里点「保存」即把当前整段聊天记录(各智能体气泡 + 步骤条等)存到后端,按用户隔离。
传 :task-id 时以它为存储主键做 upsert(已存在→更新;不存在→用该 id 新建);不传则首次保存由后端
生成 id(通过 @update:taskId 回传,下次再保存即更新这条)。
回显(两种方式):
<!-- 方式 1:挂载时传一个已存在的 taskId → 自动加载并回显该任务的聊天记录 -->
<ParallelAgentsPanel :task-id="'task-001'" :username="'demo'" :agents="agents" />
// 方式 1 变体:运行中改 taskId(双向绑定),面板会自动切到并回显那条任务
const taskId = ref<string>(""); // 留空=新任务
// <ParallelAgentsPanel :task-id="taskId" @update:taskId="id => taskId = id" ... />
taskId.value = "task-001"; // 改了之后面板自动回显 task-001
方式 2:面板右上角内置「历史」下拉——点开选一条历史任务即回显,无需写任何代码。
要点:先保存过、再用同一个 taskId(或从历史里选)才会有内容回显;没存过的新 id 第一次进去是空白
(后台会探测一次 GET /…/{id} 返回 404,属正常,面板静默处理)。
八、交互要点(与圆桌 Step2 一致)
- 输入「任务名称 + 简介」→「开始分析」→ 各智能体并行输出。运行期间禁用写文件(
write_file/str_replace)与派活/脚本(agent_orchestration/bash,防子智能体模仿总控调度);检索、查看、ask_clarification等照常 —— 所以步骤条 / 协作卡片正常显示,每个智能体只做自己那份分析。 - 主区每次只显示一个席位的消息列表;点席位头像切换要看哪个(单选)。
- 顶部席位状态条显示每个智能体的进行中 / 完成 / 出错。
- 操作区右侧有模型切换下拉(拉取后端
/api/models);选「默认」则用modelprop / 配置 / 后端回退。 切换作用于下一次「开始分析 / 重新分析」,运行中禁用。 - 「保存」存档;「历史」里选回回显;「重新分析」清空重跑。
九、注意事项
- 不会污染宿主全局样式:库未引入 Tailwind preflight,类名都在
.parallel-agents作用域内。 - 深色自带成色:面板始终深蓝深色,不随宿主明暗切换(与圆桌 Step2 观感一致)。
- 跨域:若宿主与后端不同源,后端需允许该来源的 CORS + 带
credentials;登录端点公共且 CSRF 豁免, 业务请求用 Bearer 头已绕过 CSRF。 - agent_id 必须真实:见 06-可用智能体清单.md 获取可用 id 与自查方法。