From bd426ed1d3811ed403217ca4206c2ccf3b277cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Wed, 10 Jun 2026 12:51:13 +0800 Subject: [PATCH] da --- .../task-components/task-mock-data.ts | 437 ++++++++++++++++++ frontend-web/src/utils/request.ts | 6 + .../app/gateway/routers/parallel_agents.py | 27 +- parallel-agents-vue/README.md | 15 +- parallel-agents-vue/docs/05-嵌入与深色样式.md | 10 +- parallel-agents-vue/docs/07-使用说明.md | 44 +- parallel-agents-vue/docs/08-开发文档.md | 80 ++-- parallel-agents-vue/package.json | 2 - parallel-agents-vue/src/App.vue | 6 +- parallel-agents-vue/src/index.ts | 16 +- parallel-agents-vue/src/main.ts | 1 - .../src/parallel-agents/Avatar.vue | 2 +- .../src/parallel-agents/ClarificationCard.vue | 2 +- .../src/parallel-agents/MessageBubble.vue | 2 +- .../src/parallel-agents/MessageStepsCard.vue | 4 +- .../parallel-agents/ParallelAgentsPanel.vue | 12 +- .../src/parallel-agents/ParallelSeatStrip.vue | 6 +- .../src/parallel-agents/README.md | 61 +++ .../src/parallel-agents/StepIcon.vue | 2 +- .../src/parallel-agents/index.ts | 27 ++ .../src/parallel-agents/parallel-agents.css | 192 +++++++- .../src/parallel-agents/types.ts | 8 +- .../src/parallel-agents/useParallelRun.ts | 55 ++- parallel-agents-vue/vite.config.ts | 3 +- 24 files changed, 912 insertions(+), 108 deletions(-) create mode 100644 frontend-web/src/strategy-components/components/task-components/task-mock-data.ts create mode 100644 parallel-agents-vue/src/parallel-agents/README.md create mode 100644 parallel-agents-vue/src/parallel-agents/index.ts diff --git a/frontend-web/src/strategy-components/components/task-components/task-mock-data.ts b/frontend-web/src/strategy-components/components/task-components/task-mock-data.ts new file mode 100644 index 00000000..e91db4ea --- /dev/null +++ b/frontend-web/src/strategy-components/components/task-components/task-mock-data.ts @@ -0,0 +1,437 @@ +import { TaskListItem } from './TaskManagement'; + +/** + * 任务看板假数据 —— 用于在没有后端 `/task/cop-tasks` / `/three/cop-three-tasks` + * 接口时,给「任务分析」「三情分析」两个页面提供演示数据。 + * + * 用法:把组件里的 `await service.post(url, payload)` 换成 + * `await mockCopTasks('task' | 'sentiment', taskType, payload)` + * 返回结构与真实接口保持一致:`{ data: { records, total } }`。 + */ + +export type MockColumnType = 'unanalyzed' | 'running' | 'completed'; +export type MockDataset = 'task' | 'sentiment'; + +interface MockTaskSeed { + taskName: string; + overview: string; + taskDirection: string; + taskLevel: number; // 1 一般 / 2 紧急 / 3 加急 + taskType: number; // 1 单任务 / 2 场景 / 3 会商 / 4 多智能体 / 5 检索 +} + +/** 列 → 状态码,与组件内 taskStatusMap 对齐。 */ +const COLUMN_STATUS: Record = { + unanalyzed: 0, + running: 20, + completed: 30, +}; + +/** 生成一条完整的 TaskListItem,仅覆盖有意义的字段,其余给安全默认值。 */ +function makeTask( + id: number, + column: MockColumnType, + seed: MockTaskSeed, + createTime: string, + updateTime: string, +): TaskListItem { + return { + createBy: 1001, + createTime, + deptId: null, + id, + isTop: 0, + issuingDept: '战略规划处', + keywords: null, + overview: seed.overview, + planTaskTop: 0, + platform: null, + ptaskId: null, + recommendedBasis: null, + scene: '', + sourceType: 1, + step: null, + taskContent: seed.overview, + taskDirection: seed.taskDirection, + taskEndDate: '2026-06-30 18:00:00', + taskLevel: seed.taskLevel, + taskName: seed.taskName, + taskNo: `T-${String(id).padStart(6, '0')}`, + taskStartDate: '2026-06-01 09:00:00', + taskStatus: COLUMN_STATUS[column], + taskSuperiorFlag: 0, + taskType: seed.taskType, + column, + updateBy: 1001, + updateTime, + endCount: column === 'completed' ? 1 : 0, + sumAll: 1, + progress: column === 'completed' ? 100 : column === 'running' ? 60 : 0, + taskStatusData: null, + } as TaskListItem; +} + +/** 「任务分析」页(业务码 6BF)数据种子。 */ +const TASK_SEEDS: Record = { + unanalyzed: [ + { + taskName: '夏季文旅消费季传播任务分析', + overview: + '围绕"夏季文旅消费季"主题,梳理传播目标、核心受众与潜在策略阻力,输出可执行的任务拆解建议。', + taskDirection: '王磊', + taskLevel: 2, + taskType: 1, + }, + { + taskName: '新能源补贴政策解读专题', + overview: + '针对新一轮新能源汽车补贴政策,分析公众关注焦点与误读风险点,形成政策解读传播要点清单。', + taskDirection: '李婷', + taskLevel: 1, + taskType: 5, + }, + { + taskName: '城市更新片区舆论引导任务', + overview: + '对老城区改造涉及的拆迁、安置等敏感议题进行任务目标拆解,识别需要重点回应的群体诉求。', + taskDirection: '张伟', + taskLevel: 3, + taskType: 2, + }, + { + taskName: '高校毕业季就业服务宣传', + overview: + '梳理面向应届毕业生的就业服务政策传播任务,明确分阶段触达节奏与渠道组合。', + taskDirection: '赵敏', + taskLevel: 1, + taskType: 1, + }, + { + taskName: '防汛应急科普传播任务', + overview: + '汛期来临前,分析防汛减灾科普内容的传播目标与受众分层,制定预警信息发布预案。', + taskDirection: '陈昊', + taskLevel: 2, + taskType: 1, + }, + { + taskName: '乡村振兴成果展示任务', + overview: + '围绕本地乡村振兴典型案例,拆解成果展示传播任务,确定故事化表达与素材采集方向。', + taskDirection: '周琳', + taskLevel: 1, + taskType: 2, + }, + ], + running: [ + { + taskName: '社区养老服务满意度专题分析', + overview: + '正在对社区居家养老服务的群众反馈进行任务分析,重点判断受众诉求与服务短板。', + taskDirection: '孙强', + taskLevel: 2, + taskType: 4, + }, + { + taskName: '中小企业纾困政策落地评估', + overview: + '多智能体协同分析纾困政策落地过程中的执行阻力与企业关切,形成阶段性研判。', + taskDirection: '吴静', + taskLevel: 3, + taskType: 4, + }, + { + taskName: '城市轨道交通延误舆情研判', + overview: + '针对近期地铁延误事件,正在拆解舆论传播路径与关键节点,评估引导策略有效性。', + taskDirection: '郑凯', + taskLevel: 2, + taskType: 3, + }, + { + taskName: '食品安全抽检结果发布任务', + overview: + '正在分析食品安全抽检通报的发布口径与受众反应,优化信息透明度与安抚策略。', + taskDirection: '冯雪', + taskLevel: 1, + taskType: 1, + }, + ], + completed: [ + { + taskName: '春节文化活动传播复盘', + overview: + '已完成春节系列文化活动的传播任务分析,沉淀受众画像与高互动内容规律。', + taskDirection: '黄涛', + taskLevel: 1, + taskType: 3, + }, + { + taskName: '医保改革政策宣传任务', + overview: + '已完成医保改革政策的传播目标拆解与受众分层,输出分群体沟通话术。', + taskDirection: '宋佳', + taskLevel: 2, + taskType: 4, + }, + { + taskName: '城市营商环境优化宣传', + overview: + '已完成营商环境优化举措的任务分析,明确企业端与公众端的差异化传播重点。', + taskDirection: '高鹏', + taskLevel: 1, + taskType: 2, + }, + { + taskName: '老旧小区加装电梯议题分析', + overview: + '已完成加装电梯涉及的邻里诉求与阻力识别,形成多方协商沟通建议。', + taskDirection: '何丽', + taskLevel: 2, + taskType: 3, + }, + { + taskName: '生态环保主题宣传周复盘', + overview: + '已完成环保宣传周的传播效果分析,总结渠道贡献度与可复用素材。', + taskDirection: '罗勇', + taskLevel: 1, + taskType: 1, + }, + { + taskName: '青年人才引进政策解读', + overview: + '已完成人才引进政策的受众判断与策略阻力分析,输出落地传播节奏表。', + taskDirection: '谭芳', + taskLevel: 1, + taskType: 5, + }, + ], +}; + +/** 「三情分析」页(业务码 3Q)数据种子。 */ +const SENTIMENT_SEEDS: Record = { + unanalyzed: [ + { + taskName: '暑期旅游热点情绪监测', + overview: + '对暑期热门景区相关讨论进行情绪与倾向分析,识别游客吐槽集中点与正向口碑话题。', + taskDirection: '王磊', + taskLevel: 2, + taskType: 1, + }, + { + taskName: '电价调整公众情绪研判', + overview: + '围绕居民阶梯电价调整,分析公众情绪走向与主要担忧,判断需要重点疏导的群体。', + taskDirection: '李婷', + taskLevel: 3, + taskType: 5, + }, + { + taskName: '校园周边交通安全舆情', + overview: + '对校园周边交通安全话题进行三情分析,梳理家长群体情绪与诉求强度。', + taskDirection: '张伟', + taskLevel: 2, + taskType: 1, + }, + { + taskName: '景区门票预约制讨论分析', + overview: + '分析门票预约制相关讨论的情绪分布,识别便利性与公平性两类核心关切。', + taskDirection: '赵敏', + taskLevel: 1, + taskType: 2, + }, + { + taskName: '夜间经济噪音投诉情绪', + overview: + '对夜市、夜间演出引发的噪音投诉进行情绪分析,区分居民与商户的不同立场。', + taskDirection: '陈昊', + taskLevel: 1, + taskType: 1, + }, + ], + running: [ + { + taskName: '台风预警信息传播情绪追踪', + overview: + '正在分析台风预警发布后的公众情绪变化,评估恐慌情绪与配合度的动态走势。', + taskDirection: '孙强', + taskLevel: 3, + taskType: 4, + }, + { + taskName: '学区划分调整舆论情绪', + overview: + '多智能体协同追踪学区调整话题的情绪热度与对立观点,研判潜在升级风险。', + taskDirection: '吴静', + taskLevel: 2, + taskType: 4, + }, + { + taskName: '网络热点事件情绪态势', + overview: + '正在对近期网络热点事件进行三情分析,识别情绪峰值节点与关键意见领袖。', + taskDirection: '郑凯', + taskLevel: 2, + taskType: 3, + }, + ], + completed: [ + { + taskName: '春运出行体验情绪复盘', + overview: + '已完成春运期间出行体验的情绪与倾向分析,沉淀满意度变化与高频抱怨主题。', + taskDirection: '黄涛', + taskLevel: 1, + taskType: 3, + }, + { + taskName: '惠民政策落地情绪评估', + overview: + '已完成惠民政策落地后的公众情绪评估,输出正向反馈与改进诉求清单。', + taskDirection: '宋佳', + taskLevel: 2, + taskType: 4, + }, + { + taskName: '城市内涝应对情绪分析', + overview: + '已完成强降雨内涝事件的三情分析,总结情绪演化曲线与有效安抚措施。', + taskDirection: '高鹏', + taskLevel: 2, + taskType: 1, + }, + { + taskName: '景区限流措施满意度分析', + overview: + '已完成节假日景区限流措施的情绪分析,明确游客接受度与体验改进方向。', + taskDirection: '何丽', + taskLevel: 1, + taskType: 2, + }, + { + taskName: '公共交通票价听证情绪', + overview: + '已完成票价听证会相关讨论的情绪与立场分析,输出分群体沟通建议。', + taskDirection: '罗勇', + taskLevel: 1, + taskType: 5, + }, + ], +}; + +const SEEDS: Record> = { + task: TASK_SEEDS, + sentiment: SENTIMENT_SEEDS, +}; + +/** 给同一列里的卡片生成错落有致的时间,便于「按时间倒序」展示。 */ +function buildTimes(index: number): { createTime: string; updateTime: string } { + const day = String(28 - index).padStart(2, '0'); + const hour = String(9 + (index % 8)).padStart(2, '0'); + return { + createTime: `2026-05-${day} ${hour}:15:00`, + updateTime: `2026-06-0${(index % 9) + 1} ${hour}:40:00`, + }; +} + +/** 数据集 → 列 → 完整任务列表(按 id 区分,避免两页 key 冲突)。 */ +function buildPool(dataset: MockDataset, column: MockColumnType): TaskListItem[] { + const base = dataset === 'task' ? 10000 : 20000; + const columnOffset = column === 'unanalyzed' ? 0 : column === 'running' ? 300 : 600; + return SEEDS[dataset][column].map((seed, index) => { + const { createTime, updateTime } = buildTimes(index); + return makeTask(base + columnOffset + index, column, seed, createTime, updateTime); + }); +} + +interface MockCopTasksPayload { + content?: string; + pageNum?: number; + pageSize?: number; + taskStatus?: number[]; +} + +/** 根据请求里的 taskStatus 数组反推当前查询的是哪一列。 */ +function resolveColumn(taskStatus?: number[]): MockColumnType { + const list = Array.isArray(taskStatus) ? taskStatus : []; + if (list.includes(20)) return 'running'; + if (list.includes(0) || list.includes(10)) return 'unanalyzed'; + return 'completed'; +} + +/** + * 模拟 `/task/cop-tasks` / `/three/cop-three-tasks` 接口的 body: + * 按列返回分页后的假数据,支持按 `content` 对任务名/摘要做模糊过滤。 + */ +function buildCopTasksBody(dataset: MockDataset, payload: MockCopTasksPayload) { + const { content = '', pageNum = 1, pageSize = 10, taskStatus } = payload; + const column = resolveColumn(taskStatus); + + let pool = buildPool(dataset, column); + const keyword = content.trim(); + if (keyword) { + pool = pool.filter( + (item) => + item.taskName.includes(keyword) || item.overview.includes(keyword), + ); + } + + const total = pool.length; + const start = (pageNum - 1) * pageSize; + const records = pool.slice(start, start + pageSize); + + return { code: 0, message: 'ok', data: { records, total } }; +} + +/** 命中本 mock 的接口路径 → 对应数据集。 */ +const MOCK_ROUTES: Array<{ match: string; dataset: MockDataset }> = [ + { match: '/three/cop-three-tasks', dataset: 'sentiment' }, + { match: '/task/cop-tasks', dataset: 'task' }, +]; + +/** 判断某个请求 url 是否应走假数据。 */ +export function matchTaskBoardMock(url?: string): MockDataset | null { + if (!url) return null; + const hit = MOCK_ROUTES.find((route) => url.includes(route.match)); + return hit ? hit.dataset : null; +} + +/** + * 临时假数据 axios adapter:命中任务看板接口时直接返回 mock body,不发真实请求。 + * 仅用于演示,撤掉假数据时删除 request.ts 中对它的引用即可。 + */ +export function taskBoardMockAdapter(config: { + url?: string; + data?: unknown; +}): Promise<{ data: unknown; status: number; statusText: string; headers: Record; config: unknown }> { + const dataset = matchTaskBoardMock(config.url) ?? 'task'; + + let payload: MockCopTasksPayload = {}; + try { + payload = + typeof config.data === 'string' + ? JSON.parse(config.data) + : ((config.data as MockCopTasksPayload) ?? {}); + } catch { + payload = {}; + } + + const body = buildCopTasksBody(dataset, payload); + + return new Promise((resolve) => { + // 模拟网络延迟,让 Loading 态可见。 + setTimeout(() => { + resolve({ + data: body, + status: 200, + statusText: 'OK', + headers: {}, + config, + }); + }, 280); + }); +} diff --git a/frontend-web/src/utils/request.ts b/frontend-web/src/utils/request.ts index 17c6a139..630ac4f4 100644 --- a/frontend-web/src/utils/request.ts +++ b/frontend-web/src/utils/request.ts @@ -1,4 +1,6 @@ import axios from 'axios' +// === 临时假数据(任务分析 / 三情分析看板):撤掉时删除本 import 及下方 request 拦截器中的对应块即可 === +import { matchTaskBoardMock, taskBoardMockAdapter } from '@/strategy-components/components/task-components/task-mock-data' // axios.interceptors const service = axios.create({ // baseURL: '', // url = base url + request url @@ -31,6 +33,10 @@ service.interceptors.response.use( ) service.interceptors.request.use( config => { + // === 临时假数据:任务看板两个接口直接走本地 mock,不发真实请求 === + if (matchTaskBoardMock(config.url)) { + config.adapter = taskBoardMockAdapter as any; + } // let token: any = localStorage.getItem('token'); config.headers['Authorization'] = `Bearer admin`; // if (token) { diff --git a/offline-backend-20260512/backend/app/gateway/routers/parallel_agents.py b/offline-backend-20260512/backend/app/gateway/routers/parallel_agents.py index be57f4cd..39873369 100644 --- a/offline-backend-20260512/backend/app/gateway/routers/parallel_agents.py +++ b/offline-backend-20260512/backend/app/gateway/routers/parallel_agents.py @@ -7,10 +7,12 @@ one stream and never parses LangGraph internals. Each fan-out agent runs as a pure **executing seat**: ``excluded_tools`` = ``_EXCLUDED_TOOLS`` (``write_file`` / ``str_replace`` / ``agent_orchestration`` / -``bash``) so a seat can neither write files (parallel writes would clash) nor -dispatch / run scripts (a weak model fed "总控 / 业务链条" framing would otherwise -mimic the controller and "派活"). Read-only tools + ``ask_clarification`` stay on, -so the step bar and clarification cards still work. +``bash`` / ``ask_clarification``) so a seat can neither write files (parallel +writes would clash), dispatch / run scripts (a weak model fed "总控 / 业务链条" +framing would otherwise mimic the controller and "派活"), nor pause to ask the +user for help (this panel is an unattended parallel fan-out — a seat short on +info makes a reasonable assumption and states it in its answer instead of +interrupting). Read-only tools stay on, so the step bar still works. Unified event protocol (one JSON object per ``data:`` frame):: @@ -58,18 +60,21 @@ router = APIRouter(prefix="/api/parallel-agents", tags=["parallel-agents"]) # Soft cap on parallel degree — protects remote model concurrency + sandbox. MAX_PARALLEL_AGENTS = 8 -# 禁两类工具:①**写文件**(write_file / str_replace)—— 并行席位互相写文件会打架; +# 禁三类工具:①**写文件**(write_file / str_replace)—— 并行席位互相写文件会打架; # ②**派活 / 脚本逃逸**(agent_orchestration / bash)—— 本面板里每个智能体只做自己那 # 份分析交付,绝不该扮演「总控」去调度别人。弱模型(deepseek 等)拿到带「总控 / 业务 # 链条」语气的任务后,会概率性地用 agent_orchestration 真去派活,或绕道 bash 跑脚本 # 调内部接口模仿总控调度(bug:单步单智能体链条里子智能体输出「总控调度指令…」并用 -# glob / bash 翻找派活脚本)。物理禁掉这两类即可根治。其余只读工具(ls / read_file / -# 检索)与 ask_clarification(协作卡片)保留:既不互相打架,又能正常出步骤条 / 要澄清。 +# glob / bash 翻找派活脚本)。③**用户协助**(ask_clarification)—— 本面板是「无人值守」 +# 的并行扇出,没有让单个席位中途打断、向用户要澄清的交互位;禁掉后席位遇到信息不足时 +# 自行做合理假设并把假设写进正文交付,而不是挂起等人。物理禁掉这三类即可根治。其余只读 +# 工具(ls / read_file / 检索)保留:既不互相打架,又能正常出步骤条。 _EXCLUDED_TOOLS: list[str] = [ "write_file", # 并行不互相写文件打架 "str_replace", "agent_orchestration", # 子智能体不派活 / 不调度(防模仿总控) "bash", # 禁跑脚本(防绕道脚本调内部接口模仿派活) + "ask_clarification", # 禁「用户协助」:并行无人值守,不向用户要澄清,自己合理假设并交付 ] @@ -276,6 +281,14 @@ def _build_task_message(task_name: str, brief: str) -> str: "调度对象 / 分配给『…』的任务 / agent_name」之类调度内容,严禁罗列或转派其他席位的任务,严禁调用" "任何派活 / 调度类工具,也不要用脚本(bash / python)去调用内部接口或翻找派活脚本。" ) + # 无人值守护栏:本轮并行执行没有让你中途向用户要澄清的交互位(已禁用用户协助)。遇到 + # 信息不足时,请基于已有信息做出**合理假设**并在正文中**注明你的假设**,照常给出交付, + # 不要反问用户、不要把交付挂起等待补充。 + parts.append( + "【无人值守】本轮为并行无人值守执行,没有与你来回澄清的环节。若信息不足,请自行做出" + "**合理假设**并在交付中**明确写出你假设了什么**,然后照常完成分析;不要反问用户、不要" + "要求补充信息后再继续,也不要把结论挂起等待确认。" + ) return "\n\n".join(parts) diff --git a/parallel-agents-vue/README.md b/parallel-agents-vue/README.md index c4602f35..fa0169a3 100644 --- a/parallel-agents-vue/README.md +++ b/parallel-agents-vue/README.md @@ -25,11 +25,23 @@ pnpm build:lib # 产出 dist/parallel-agents-vue.{js,umd.cjs} + dist/parallel-a ## 嵌入其它 Vue 项目 +两种方式(详见 [docs/07-使用说明.md](./docs/07-使用说明.md)): + +**A. 按包引入**(已 `build:lib`): + ```ts import { ParallelAgentsPanel } from "parallel-agents-vue"; import "parallel-agents-vue/style.css"; ``` +**B. 直接拷源码**(适合要改源码的人):把整个 **`src/parallel-agents/` 文件夹**拷进你的项目 `src/` 下, +样式由其 `index.ts` 自动引入,**无需 Tailwind / 任何 CSS 框架**: + +```ts +import { ParallelAgentsPanel } from "@/parallel-agents"; // 或 "./parallel-agents" +``` +> 仅需 `vue` 与 `markdown-it` 两个运行依赖。 + ```vue @@ -76,4 +88,5 @@ import "parallel-agents-vue/style.css"; - `@saved="(task) => ..."` —— 保存成功(含新建/更新)后回传 `SavedTask`。 - `@update:taskId="(id) => ..."` —— 当前任务 id 变化(保存 / 加载历史时)。 -> 样式作用域全部包在根类 `.parallel-agents` 下,且**不引入 Tailwind preflight**,不会污染宿主全局样式。 +> 样式作用域全部包在根类 `.parallel-agents` 下,**不依赖 Tailwind**(布局类是面板自带的作用域工具类子集), +> 不会污染宿主全局样式。 diff --git a/parallel-agents-vue/docs/05-嵌入与深色样式.md b/parallel-agents-vue/docs/05-嵌入与深色样式.md index c6f22d13..708cc970 100644 --- a/parallel-agents-vue/docs/05-嵌入与深色样式.md +++ b/parallel-agents-vue/docs/05-嵌入与深色样式.md @@ -84,15 +84,15 @@ pnpm build:lib ## PA-EMBED-06 · 不污染宿主全局样式(P0) -**目的**:核对**未引入 Tailwind preflight**(不重置宿主全局标签样式)。 +**目的**:核对面板**不依赖 Tailwind**、不重置宿主全局标签样式(无任何裸标签选择器 / reset)。 **操作步骤** -1. 在一个有自己样式的宿主页里嵌入面板(页面有 `h1/p/button/ul` 等默认样式)。 +1. 在一个有自己样式、且**没装 Tailwind** 的宿主页里嵌入面板(页面有 `h1/p/button/ul` 等默认样式)。 **预期结果** -- 嵌入后,宿主页面**自身**的 `h1/p/button/列表/边距` 等样式**不被改变**(没有被 Tailwind 的 reset 抹平)。 -- 面板内部样式正常(不依赖宿主提供 Tailwind)。 -- 类名都在 `.parallel-agents` 作用域下,不与宿主类名冲突。 +- 嵌入后,宿主页面**自身**的 `h1/p/button/列表/边距` 等样式**不被改变**(面板样式无全局 reset、无裸标签规则)。 +- 面板内部样式正常(**不需要宿主提供 Tailwind**;布局类是面板自带的作用域工具类子集)。 +- 所有规则都在 `.parallel-agents` 作用域下,不与宿主类名冲突。 --- diff --git a/parallel-agents-vue/docs/07-使用说明.md b/parallel-agents-vue/docs/07-使用说明.md index 25d8acf4..afe4febb 100644 --- a/parallel-agents-vue/docs/07-使用说明.md +++ b/parallel-agents-vue/docs/07-使用说明.md @@ -20,6 +20,8 @@ 2. **样式**:`parallel-agents-vue/style.css`(一次性引入即可,样式作用域全在 `.parallel-agents` 下) > 依赖说明:`vue ^3.4`(宿主提供,库不打包 vue);`markdown-it` 已打进库内,无需宿主安装。 +> **无需 Tailwind 或任何 CSS 框架**:布局样式已内置为 `parallel-agents.css` 末尾的「最小工具类子集」 +> (全部作用域在 `.parallel-agents` 下,不污染宿主)。宿主项目**不用**装 / 配 Tailwind。 --- @@ -41,21 +43,32 @@ import "parallel-agents-vue/style.css"; ``` -### 方式 B:直接拷贝源码(无需发包) +### 方式 B:直接拷贝源码(无需发包,**推荐给需要改源码的人**) -把本项目 `src/` 下这些拷进宿主项目(保持相对结构),按相对路径引入 `ParallelAgentsPanel.vue` + -`styles/parallel-agents.css` 即可: +所有实现已收进**一个自包含文件夹** `src/parallel-agents/`。把**整个文件夹**拷进宿主项目的 `src/` +下即可,内部全是相对路径引用、不依赖任何构建别名: ``` -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 +src/parallel-agents/ ← 整个文件夹拷走即用 + index.ts 入口:自动引样式 + 导出组件/类型 + ParallelAgentsPanel.vue 主组件 + ParallelSeatStrip.vue · MessageBubble.vue · MessageStepsCard.vue · StepIcon.vue + ClarificationCard.vue · MarkdownContent.vue · Avatar.vue (子组件) + useParallelRun.ts 并行运行编排 + api.ts · types.ts · config.ts · avatar-constants.ts · step-display.ts + parallel-agents.css 作用域样式(深色 token + 语义类 + 工具类子集,无 Tailwind) + README.md 本文件夹的速用说明 ``` + +引入(样式由 `index.ts` 自动引入,无需手动 import css): + +```ts +import { ParallelAgentsPanel } from "@/parallel-agents"; +// 或相对路径: import { ParallelAgentsPanel } from "./parallel-agents"; +``` + 宿主需有 `markdown-it` 依赖(`pnpm add markdown-it`),并保证构建支持 `.vue`(Vite/@vitejs/plugin-vue)。 +**不需要 Tailwind**。 --- @@ -446,6 +459,9 @@ function readOne(id: string) { ``` `AgentResult = { agent_id, name, content, status }`,`content` 即该智能体模型返回的正文(Markdown)。 +`status` 取值:`pending | running | done | clarify | error`。**`clarify` = 该智能体在等用户协助 +(待确认),不是已完成**——宿主判断「是否全部完成」时应排除 `clarify`(例如 +`results.every(r => r.status === "done")`),不要把待协助当成 done。 `defineExpose` 还暴露了 `reanalyze()` / `start()` / `save()` / `cancel()` / `loadTask(id)` 等方法及 `running` / `saving` / `hasResults` / `canStart` / `history` 等状态,完整清单见 [§六·二](#六二暴露的方法与状态模板-ref)。 @@ -503,7 +519,10 @@ taskId.value = "task-001"; // 改了之后面板自动回显 task- 防子智能体模仿总控调度);检索、查看、`ask_clarification` 等照常 —— 所以**步骤条 / 协作卡片正常 显示**,每个智能体只做自己那份分析。 - 主区每次只显示**一个**席位的消息列表;**点席位头像切换**要看哪个(单选)。 -- 顶部席位状态条显示每个智能体的进行中 / 完成 / 出错。 +- 顶部席位状态条显示每个智能体的进行中 / 完成 / **待协助** / 出错;待协助数量会单独标「N 待协助」。 +- **用户协助(澄清)**:智能体要澄清时该席位变「待协助」(不是完成),气泡里弹协作卡片。多个智能体 + 同时待协助时**可分别点协助、互不阻塞**(协助 A 不会禁用 B/C 的卡片);提交回答后该席位自动带上 + 补充重跑。 - **任务名 / 简介 / 模型 / 按钮 / 历史下拉全部在宿主侧**:模型空 = `model` prop / 配置 / 后端回退; 模型作用于**下一次**`reanalyze()`。 - `panel.save()` 存档;`panel.loadTask(id)` 回显;`panel.reanalyze()` 清空重跑;`panel.cancel()` 停止。 @@ -514,7 +533,8 @@ taskId.value = "task-001"; // 改了之后面板自动回显 task- ## 九、注意事项 -- **不会污染宿主全局样式**:库未引入 Tailwind preflight,类名都在 `.parallel-agents` 作用域内。 +- **不会污染宿主全局样式**:**不依赖 Tailwind**,布局类已内置为作用域工具类子集,所有规则都在 + `.parallel-agents` 下,绝不外泄到宿主页面。 - **深色自带成色**:面板始终深蓝深色,不随宿主明暗切换(与圆桌 Step2 观感一致)。 - **跨域**:若宿主与后端不同源,后端需允许该来源的 CORS + 带 `credentials`;登录端点公共且 CSRF 豁免, 业务请求用 Bearer 头已绕过 CSRF。 diff --git a/parallel-agents-vue/docs/08-开发文档.md b/parallel-agents-vue/docs/08-开发文档.md index 0cf3cd45..e57b2f37 100644 --- a/parallel-agents-vue/docs/08-开发文档.md +++ b/parallel-agents-vue/docs/08-开发文档.md @@ -23,7 +23,7 @@ | 框架 | Vue 3(`