kd-chatbot-ui-vue2 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,515 +1,554 @@
1
- # kd-chatbot-ui-vue2
2
-
3
- Vue **2.7** 智能体会话组件库(由 Vue3 包 `kd-chatbot-ui` 迁移)。
4
-
5
- 请求鉴权由宿主传入 `request`,组件库不写死 token / 拦截器。
6
-
7
- | 模式 | 组件 | 适用场景 |
8
- |------|------|----------|
9
- | **适配(推荐同协议)** | `AgentChatAdaptPanel` | 流程与 interpret 相近:组件内调接口;地址、入参字段由宿主配置 |
10
- | **受控(完全自定义)** | `AgentChatPanel` | 路径/入参/出参都可能不同:宿主自己调接口,props 传 `sessions` |
11
-
12
- ---
13
-
14
- ## 0. 与 Vue3 版差异(必读)
15
-
16
- | 项 | Vue3(`kd-chatbot-ui`) | Vue2(本包) |
17
- |----|-------------------------|--------------|
18
- | Vue | `^3.5` | `^2.7` |
19
- | UI | Element Plus | Element UI `^2.15` |
20
- | 状态 | Pinia `^3` | Pinia `^2.1` |
21
- | 气泡 / 输入框 | `vue-element-plus-x` | 包内 `ChatBubble` / `ChatSender` |
22
- | 历史栏双向绑定 | `v-model:history-open` | `:history-open.sync` |
23
- | 插件安装 | `app.use(plugin)` | `Vue.use(plugin)` |
24
- | 本地存储 key | `kdChatbotUi_v3` | `kdChatbotUi_vue2_v1`(与 Vue3 隔离) |
25
-
26
- **接口契约相同**:`request` / `endpoints` / `requestParams` / `reloadKey` / `responseFields` / `theme` 等与 Vue3 版一致。
27
-
28
- ---
29
-
30
- ## 1. `AgentChatAdaptPanel`(优先阅读)
31
-
32
- 组件内部完成:拉会话列表、创建会话、发问、轮询进度、取消、写 store。
33
-
34
- 宿主只需要传:**请求函数**、**接口地址**、**传参映射**、**隔离维度**。
35
-
36
- ### 1.1 最小用法
37
-
38
- ```vue
39
- <template>
40
- <div class="agent-chat-page">
41
- <AgentChatAdaptPanel
42
- :request="request"
43
- :theme="theme"
44
- :endpoints="endpoints"
45
- :request-params="requestParams"
46
- :reload-key="reloadKey"
47
- :tips="agentTips"
48
- :show-open-in-browser="false"
49
- />
50
- </div>
51
- </template>
52
-
53
- <script>
54
- import {
55
- AgentChatAdaptPanel
56
- } from "kd-chatbot-ui-vue2";
57
- import "kd-chatbot-ui-vue2/style.css";
58
- import request from "@/utils/request";
59
-
60
- export default {
61
- name: "AgentChatPage",
62
- components: { AgentChatAdaptPanel },
63
- data() {
64
- return {
65
- request,
66
- theme: "light",
67
- /** 快捷提示(多项):value 文案 / content 发送内容 / type 提问类型 */
68
- agentTips: [
69
- {
70
- id: "default_analysis",
71
- value: "整体分析",
72
- content: "请对动力学计算结果进行整体分析",
73
- type: "default_analysis"
74
- }
75
- ],
76
- endpoints: {
77
- createSession: "/ds-dynamics-alg-service/interpret/sessions",
78
- listSessions: "/ds-dynamics-alg-service/interpret/sessions",
79
- history: "/ds-dynamics-alg-service/interpret/history/:sessionId",
80
- ask: "/ds-dynamics-alg-service/interpret/chat/ask",
81
- cancel: "/ds-dynamics-alg-service/interpret/chat/cancel",
82
- progress: "/ds-dynamics-alg-service/interpret/chat/progress"
83
- }
84
- };
85
- },
86
- computed: {
87
- wellboreId() {
88
- return String(this.$store?.state?.well?.wellboreId || "");
89
- },
90
- mainId() {
91
- return String(this.$store?.state?.well?.mainId || "");
92
- },
93
- tripId() {
94
- return String(this.$store?.state?.well?.tripId || "");
95
- },
96
- reloadKey() {
97
- return `${this.wellboreId}|${this.mainId}|${this.tripId}`;
98
- },
99
- /**
100
- * 各接口真实传参。
101
- * - 主应用字段:在闭包里直接取(wellboreId 等)
102
- * - 包内字段:用参数 runtime(sessionId / taskId / content / type / since)
103
- */
104
- requestParams() {
105
- const self = this;
106
- return {
107
- createSession: () => ({
108
- body: {
109
- wellbore_id: self.wellboreId,
110
- main_id: self.mainId,
111
- trip_id: self.tripId
112
- }
113
- }),
114
- listSessions: () => ({
115
- query: {
116
- wellbore_id: self.wellboreId,
117
- main_id: self.mainId,
118
- trip_id: self.tripId
119
- }
120
- }),
121
- history: runtime => ({
122
- path: { sessionId: runtime.sessionId }
123
- }),
124
- ask: runtime => ({
125
- body: {
126
- wellbore_id: self.wellboreId,
127
- main_id: self.mainId,
128
- trip_id: self.tripId,
129
- session_id: runtime.sessionId,
130
- type: runtime.type,
131
- content: runtime.content
132
- }
133
- }),
134
- cancel: runtime => ({
135
- body: { task_id: runtime.taskId }
136
- }),
137
- progress: runtime => ({
138
- query: {
139
- task_id: runtime.taskId,
140
- since: runtime.since
141
- }
142
- })
143
- };
144
- }
145
- }
146
- };
147
- </script>
148
- ```
149
-
150
- > 不必再传 `:context`。主应用字段写在 `requestParams` 闭包里即可。
151
- > `endpoints` 已是完整路径(以 `/` 开头)时,不必再传 `base-url`。
152
- > 宿主需已安装并注册 **Pinia**、**Element UI**。
153
-
154
- ### 1.2 Props
155
-
156
- | 模板属性 | 类型 | 说明 |
157
- |----------|------|------|
158
- | `request` | `AgentChatRequestFn` | 宿主请求函数(带 token)。不传则用 `fetch`(无鉴权) |
159
- | `base-url` | `string` | 可选统一前缀。`endpoints` 已给完整路径时可省略。模板写 `base-url`(不要写成 `baseURL`) |
160
- | `endpoints` | `AgentChatEndpoints` | 各接口路径。以 `/` 开头视为站点绝对路径,不再拼 `base-url` |
161
- | `request-params` | `AgentChatRequestParams` | **各接口传参映射**(主应用字段 + 包内 runtime) |
162
- | `reload-key` | `string \| number` | 井/趟等维度变化时重拉会话。建议传 `` `${wellboreId}|${mainId}|${tripId}` `` |
163
- | `response-fields` | `AgentChatResponseFields` | 响应字段名。默认 `session_id` / `task_id` / `code === "OK"` |
164
- | `theme` | `"light" \| "dark" \| "gray" \| "white"` | 面板主题;`white` 按 `light` 处理 |
165
- | `tips` | `AgentChatTip[]` | 底部快捷提示(**多项**)。每项:`value` 文案、`content` 发送内容、`type` 提问类型。不传则用默认「整体分析」。样式已 `flex-wrap`,多了会换行 |
166
- | `show-open-in-browser` | `boolean` | 是否显示「浏览器打开」,默认 `true` |
167
- | `poll-interval-ms` | `number` | 进度轮询间隔,默认 `500` |
168
- | `context` | `AgentChatContext` | **已不推荐**。仅兼容旧写法;新接入请用 `request-params` |
169
- | `required-context` | `string[]` | 仅在仍使用 `context` 时做必填校验 |
170
-
171
- ### 1.3 Events
172
-
173
- | 事件 | 说明 |
174
- |------|------|
175
- | `open-browser` | 点击「浏览器打开」。其它交互(发送/切会话/取消)由面板内部处理;新开页由宿主自行 `window.open` |
176
-
177
- ### 1.3.1 `tips` 快捷提示(多项、字段均可动态)
178
-
179
- ```js
180
- agentTips: [
181
- {
182
- id: "default_analysis",
183
- value: "整体分析", // 按钮文案
184
- content: "请对动力学计算结果进行整体分析", // 发送内容
185
- type: "default_analysis" // ask.type
186
- }
187
- // 继续追加即可
188
- ]
189
- ```
190
-
191
- 模板:`:tips="agentTips"`。也可 `import { DEFAULT_AGENT_CHAT_TIPS } from "kd-chatbot-ui-vue2"` 再改。
192
-
193
- ### 1.4 两套字段从哪里来
194
-
195
- | 来源 | 例子 | 怎么写进请求 |
196
- |------|------|----------------|
197
- | **主应用** | `wellboreId`、`mainId`、`tripId` | 在 `requestParams` **闭包里直接取** |
198
- | **包内 runtime** | `sessionId`、`taskId`、`content`、`type`、`since` | mapper 的参数 `runtime` |
199
-
200
- `runtime` 由包在发请求前组装,宿主**不用**自己存 `sessionId`:
201
-
202
- 1. 调创建会话 / 拉列表后,包从响应里读出 `session_id`(字段名可由 `response-fields` 改)
203
- 2. 写入包内 store:`sessions[].id` + `activeId`
204
- 3. 用户发送时取出当前会话 id,连同 `content`、`type` 放进 `runtime`
205
- 4. 调用你写的 mapper,例如 `session_id: runtime.sessionId`
206
-
207
- `taskId` 同理:来自 ask / history 响应,用于 cancel、progress。
208
-
209
- ### 1.5 `requestParams` 返回结构
210
-
211
- ```ts
212
- type AgentChatParamMapper = (
213
- runtime: AgentChatCallRuntime
214
- ) => {
215
- path?: Record<string, unknown>; // 替换 URL 里的 :name / {name}
216
- query?: Record<string, unknown>; // GET 查询参数
217
- body?: Record<string, unknown>; // POST body
218
- };
219
- ```
220
-
221
- | 接口 key | 常用写法 |
222
- |----------|----------|
223
- | `createSession` | `body`:主应用隔离字段 |
224
- | `listSessions` | `query`:主应用隔离字段 |
225
- | `history` | `path: { sessionId: runtime.sessionId }` 填 `:sessionId` |
226
- | `ask` | `body`:主应用字段 + `runtime.sessionId/type/content` |
227
- | `cancel` | `body: { task_id: runtime.taskId }` |
228
- | `progress` | `query: { task_id, since }` |
229
-
230
- 只写需要改的接口;未写的接口仍走包内默认 interpret 字段。
231
-
232
- ### 1.6 换项目时怎么改
233
-
234
- **只换字段名:**
235
-
236
- ```js
237
- ask: runtime => ({
238
- body: {
239
- wellId: this.wellId, // 你们自己的主应用字段
240
- chatId: runtime.sessionId, // 包内 sessionId → 你们的 chatId
241
- msg: runtime.content
242
- }
243
- })
244
- ```
245
-
246
- **路径占位也不同:**
247
-
248
- ```js
249
- // endpoints
250
- history: "/xxx/history/:conversationId"
251
-
252
- // requestParams
253
- history: runtime => ({
254
- path: { conversationId: runtime.sessionId }
255
- })
256
- ```
257
-
258
- **响应字段不同:**
259
-
260
- ```vue
261
- <AgentChatAdaptPanel
262
- :response-fields="{ sessionId: 'id', taskId: 'taskId', okValue: 0 }"
263
- ...
264
- />
265
- ```
266
-
267
- 包读出后仍放入 `runtime.sessionId` / `runtime.taskId`,后续映射不变。
268
-
269
- ### 1.7 `endpoints` 路径规则
270
-
271
- - `http(s)://...`:原样使用
272
- - 以 `/` 开头的覆盖路径:站点绝对路径,**不拼** `base-url`
273
- - 其它相对路径:拼在 `base-url` 后面
274
- - `history` 支持 `:sessionId` 或 `{sessionId}`(或你在 `path` 里声明的其它占位名)
275
-
276
- ### 1.8 约定接口(相对默认)
277
-
278
- 未覆盖 `endpoints` 时,相对 `base-url`:
279
-
280
- - `POST /sessions` — 创建会话
281
- - `GET /sessions` — 会话列表
282
- - `GET /history/:sessionId` — 历史
283
- - `POST /chat/ask` — 提问(返回 `task_id`)
284
- - `POST /chat/cancel` — 取消
285
- - `GET /chat/progress` — 轮询进度
286
-
287
- 默认成功码:`code === "OK"`。
288
-
289
- ---
290
-
291
- ## 2. `AgentChatPanel`(受控模式)
292
-
293
- 宿主自己调接口,用 props 传入展示数据;用户操作通过事件抛回宿主。
294
-
295
- ### 2.1 Props / Events
296
-
297
- | Props | 说明 |
298
- |-------|------|
299
- | `sessions` | `AgentSession[]` |
300
- | `active-id` | 当前会话 id |
301
- | `history-open` | 历史侧栏;用 **`:history-open.sync`**(不要用 `v-model:history-open`) |
302
- | `is-replying` | 是否回复中 |
303
- | `tips` / `theme` / `show-open-in-browser` | 同适配面板 |
304
-
305
- | Events | 说明 |
306
- |--------|------|
307
- | `send` | `(payload: { text, type?, tip? })` |
308
- | `select-session` | `(sessionId)` |
309
- | `create-session` | 新建 |
310
- | `cancel-reply` | 停止生成 |
311
- | `clear-session` | 清空当前会话 |
312
- | `update:historyOpen` | 切换历史栏(配合 `.sync`) |
313
- | `open-browser` | 浏览器打开 |
314
-
315
- ### 2.2 示例
316
-
317
- ```vue
318
- <template>
319
- <AgentChatPanel
320
- :sessions="sessions"
321
- :active-id="activeId"
322
- :history-open.sync="historyOpen"
323
- :is-replying="isReplying"
324
- @send="onSend"
325
- @select-session="onSelect"
326
- @create-session="onCreate"
327
- @cancel-reply="onCancel"
328
- @clear-session="onClear"
329
- />
330
- </template>
331
-
332
- <script>
333
- import { AgentChatPanel } from "kd-chatbot-ui-vue2";
334
- import "kd-chatbot-ui-vue2/style.css";
335
-
336
- export default {
337
- components: { AgentChatPanel },
338
- data() {
339
- return {
340
- sessions: [],
341
- activeId: "",
342
- historyOpen: false,
343
- isReplying: false
344
- };
345
- },
346
- methods: {
347
- async onSend({ text, type }) {
348
- this.isReplying = true;
349
- // 调你们自己的接口,写入 sessions
350
- this.isReplying = false;
351
- },
352
- onSelect(id) {
353
- this.activeId = id;
354
- },
355
- onCreate() {},
356
- onCancel() {},
357
- onClear() {}
358
- }
359
- };
360
- </script>
361
- ```
362
-
363
- 会话消息结构:
364
-
365
- ```ts
366
- interface AgentSession {
367
- id: string;
368
- title: string;
369
- content: AgentMessage[];
370
- pinned?: boolean;
371
- badge?: number;
372
- updatedAt?: number;
373
- snippet?: string;
374
- }
375
-
376
- interface AgentMessage {
377
- type: "ask" | "answer";
378
- placement: "start" | "end";
379
- content: string;
380
- segments?: { type: "reasoning" | "answer"; content: string }[];
381
- }
382
- ```
383
-
384
- 流式回复:持续更新当前会话最后一条 `answer.segments`,再通过 `:sessions` 传入即可。
385
-
386
- ---
387
-
388
- ## 3. 安装与依赖
389
-
390
- ### 3.1 安装
391
-
392
- ```bash
393
- npm i kd-chatbot-ui-vue2
394
- # 或 yarn / pnpm
395
- ```
396
-
397
- 本地联调(file 依赖示例):
398
-
399
- ```json
400
- "kd-chatbot-ui-vue2": "file:../agent-chat-components-vue2"
401
- ```
402
-
403
- 修改组件库后需在组件库目录执行 `npm run build`,宿主侧必要时重新安装该依赖。
404
-
405
- ### 3.2 Peer 依赖
406
-
407
- | 包 | 版本参考 |
408
- |----|----------|
409
- | `vue` | `^2.7` |
410
- | `vue-template-compiler` | 与 `vue` 同版本 |
411
- | `pinia` | `^2.1`(需配合 Vue 2.7) |
412
- | `element-ui` | `^2.15` |
413
- | `echarts` | `^5.5` |
414
- | `marked` | `^15` / `^16` / `^18` |
415
- | `dompurify` | `^3` |
416
-
417
- 宿主入口示例:
418
-
419
- ```js
420
- import Vue from "vue";
421
- import ElementUI from "element-ui";
422
- import "element-ui/lib/theme-chalk/index.css";
423
- import { createPinia, PiniaVuePlugin } from "pinia";
424
- import KdChatbotUi from "kd-chatbot-ui-vue2";
425
- import "kd-chatbot-ui-vue2/style.css";
426
-
427
- Vue.use(ElementUI);
428
- Vue.use(PiniaVuePlugin);
429
- Vue.use(KdChatbotUi); // 可选:全局注册 KdChatPanel / KdChatAdaptPanel / KdChatView
430
-
431
- const pinia = createPinia();
432
-
433
- new Vue({
434
- pinia,
435
- render: h => h(App)
436
- }).$mount("#app");
437
- ```
438
-
439
- 也可不 `Vue.use(KdChatbotUi)`,在页面里按需:
440
-
441
- ```js
442
- import { AgentChatAdaptPanel } from "kd-chatbot-ui-vue2";
443
- ```
444
-
445
- ### 3.3 样式
446
-
447
- ```js
448
- import "kd-chatbot-ui-vue2/style.css";
449
- ```
450
-
451
- ---
452
-
453
- ## 4. 导出一览
454
-
455
- ```ts
456
- import {
457
- AgentChatAdaptPanel,
458
- AgentChatPanel,
459
- AgentChatView,
460
- useAgentChat,
461
- useAgentChatStore,
462
- createAgentChatClient,
463
- buildInterpretContext,
464
- INTERPRET_POLL_INTERVAL_MS
465
- } from "kd-chatbot-ui-vue2";
466
-
467
- import type {
468
- AgentChatEndpoints,
469
- AgentChatRequestParams,
470
- AgentChatRequestFn,
471
- AgentChatCallRuntime,
472
- AgentChatResponseFields,
473
- AgentChatContext,
474
- AgentSession,
475
- AgentMessage,
476
- AgentChatTip,
477
- AgentChatSendPayload,
478
- AgentChatTheme
479
- } from "kd-chatbot-ui-vue2";
480
- ```
481
-
482
- 默认导出为 Vue 插件:`Vue.use(KdChatbotUi)`。
483
-
484
- ---
485
-
486
- ## 5. 打包与发布
487
-
488
- ```bash
489
- cd agent-chat-components-vue2
490
- npm install
491
- npm run build # 输出 dist/kd-chatbot-ui.js、kd-chatbot-ui.css、类型声明
492
- ```
493
-
494
- 发布:
495
-
496
- ```bash
497
- npm publish # prepublishOnly 会先 build
498
- ```
499
-
500
- ---
501
-
502
- ## 6. 怎么选模式
503
-
504
- - 后端仍是「会话 + ask + progress 轮询」这一套,只是路径/字段名不同 → **`AgentChatAdaptPanel`** + `endpoints` + `requestParams`
505
- - 协议完全不同,或宿主已有完整编排 → **`AgentChatPanel`**,自己管接口与 `sessions`
506
-
507
- Vue3 项目请用姊妹包 `kd-chatbot-ui`,不要混用本包。
508
-
509
- ---
510
-
511
- ## 7. 版本
512
-
513
- - 包名:`kd-chatbot-ui-vue2`
514
- - 版本:见 `package.json` 的 `version`
515
- - License:MIT
1
+ # kd-chatbot-ui-vue2
2
+
3
+ Vue **2.7** 智能体会话组件库。与姊妹包 [`kd-chatbot-ui`](../kd-chatbot-ui)(Vue 3)接口契约对齐;请求鉴权由宿主传入 `request`,组件库不写死 token / baseURL。
4
+
5
+ 本包位于 Monorepo:`agent-chat-components/packages/kd-chatbot-ui-vue2`。
6
+
7
+ | 模式 | 组件 | 适用场景 |
8
+ |------|------|----------|
9
+ | **适配(推荐)** | `AgentChatAdaptPanel` | 流程与 interpret 相近:组件内调接口;路径与入参由宿主配置 |
10
+ | **受控** | `AgentChatPanel` | 协议完全自定义:宿主自己调接口,用 props 传入 `sessions` |
11
+
12
+ ---
13
+
14
+ ## 目录
15
+
16
+ 1. [与 Vue3 版差异](#0-与-vue3-版差异必读)
17
+ 2. [安装与依赖](#1-安装与依赖)
18
+ 3. [AgentChatAdaptPanel](#2-agentchatadaptpanel推荐)
19
+ 4. [AgentChatPanel](#3-agentchatpanel受控模式)
20
+ 5. [导出一览](#4-导出一览)
21
+ 6. [开发与发布](#5-开发与发布)
22
+ 7. [怎么选模式](#6-怎么选模式)
23
+
24
+ ---
25
+
26
+ ## 0. 与 Vue3 版差异(必读)
27
+
28
+ | 项 | Vue3(`kd-chatbot-ui`) | Vue2(本包) |
29
+ |----|-------------------------|--------------|
30
+ | 包名 | `kd-chatbot-ui` | `kd-chatbot-ui-vue2` |
31
+ | Vue | `^3.5` | `^2.7`(不支持 2.6 及更早) |
32
+ | UI | Element Plus | Element UI `^2.15` |
33
+ | 状态 | Pinia `^3` | Pinia `^2.1` |
34
+ | 气泡 / 输入框 | `vue-element-plus-x` | 包内 `ChatBubble` / `ChatSender` |
35
+ | 历史栏双向绑定 | `v-model:history-open` | `:history-open.sync` |
36
+ | 插件安装 | `app.use(plugin)` | `Vue.use(plugin)` |
37
+ | 本地存储 key | `kdChatbotUi_v3` | `kdChatbotUi_vue2_v1`(与 Vue3 隔离) |
38
+
39
+ **接口契约相同**:`request` / `endpoints` / `requestParams` / `reloadKey` / `responseFields` / `theme` / `tips` 等与 Vue3 版一致。
40
+ **不要**在同一个 Vue 应用里同时安装两套包。
41
+
42
+ ---
43
+
44
+ ## 1. 安装与依赖
45
+
46
+ ### 1.1 安装
47
+
48
+ ```bash
49
+ npm i kd-chatbot-ui-vue2
50
+ # 或 yarn / pnpm
51
+ ```
52
+
53
+ 本地联调(指向 Monorepo 内本包):
54
+
55
+ ```json
56
+ {
57
+ "dependencies": {
58
+ "kd-chatbot-ui-vue2": "link:../agent-chat-components/packages/kd-chatbot-ui-vue2"
59
+ }
60
+ }
61
+ ```
62
+
63
+ 修改源码后,在 Monorepo 根目录执行:
64
+
65
+ ```bash
66
+ pnpm build:vue2
67
+ ```
68
+
69
+ 宿主侧如未热更新到最新 `dist`,可再执行一次 `pnpm install` / 重启开发服务。
70
+
71
+ ### 1.2 Peer 依赖
72
+
73
+ | 包 | 版本 |
74
+ |----|------|
75
+ | `vue` | `^2.7` |
76
+ | `vue-template-compiler` | 与 `vue` **同版本** |
77
+ | `pinia` | `^2.1`(配合 Vue 2.7) |
78
+ | `element-ui` | `^2.15` |
79
+ | `echarts` | `^5.5` |
80
+ | `marked` | `^15` / `^16` / `^18` |
81
+ | `dompurify` | `^3` |
82
+
83
+ ### 1.3 宿主入口
84
+
85
+ ```js
86
+ import Vue from "vue";
87
+ import ElementUI from "element-ui";
88
+ import "element-ui/lib/theme-chalk/index.css";
89
+ import { createPinia, PiniaVuePlugin } from "pinia";
90
+ import KdChatbotUi from "kd-chatbot-ui-vue2";
91
+ import "kd-chatbot-ui-vue2/style.css";
92
+
93
+ Vue.use(ElementUI);
94
+ Vue.use(PiniaVuePlugin);
95
+ Vue.use(KdChatbotUi); // 可选:全局注册 KdChatPanel / KdChatAdaptPanel / KdChatView
96
+
97
+ const pinia = createPinia();
98
+
99
+ new Vue({
100
+ pinia,
101
+ render: h => h(App)
102
+ }).$mount("#app");
103
+ ```
104
+
105
+ 也可不 `Vue.use`,在页面内按需引入:
106
+
107
+ ```js
108
+ import { AgentChatAdaptPanel } from "kd-chatbot-ui-vue2";
109
+ import "kd-chatbot-ui-vue2/style.css";
110
+ ```
111
+
112
+ ---
113
+
114
+ ## 2. `AgentChatAdaptPanel`(推荐)
115
+
116
+ 组件内部完成:拉会话列表、创建会话、发问、轮询进度、取消、写 store。
117
+ 宿主只需传:**请求函数**、**接口地址**、**传参映射**、**隔离维度**。
118
+
119
+ ### 2.1 最小用法
120
+
121
+ ```vue
122
+ <template>
123
+ <div class="agent-chat-page">
124
+ <AgentChatAdaptPanel
125
+ :request="request"
126
+ :theme="theme"
127
+ :endpoints="endpoints"
128
+ :request-params="requestParams"
129
+ :reload-key="reloadKey"
130
+ :tips="agentTips"
131
+ :show-open-in-browser="false"
132
+ />
133
+ </div>
134
+ </template>
135
+
136
+ <script>
137
+ import { AgentChatAdaptPanel } from "kd-chatbot-ui-vue2";
138
+ import "kd-chatbot-ui-vue2/style.css";
139
+ import request from "@/utils/request";
140
+
141
+ export default {
142
+ name: "AgentChatPage",
143
+ components: { AgentChatAdaptPanel },
144
+ data() {
145
+ return {
146
+ request,
147
+ theme: "light",
148
+ /** 快捷提示(多项):value 文案 / content 发送内容 / type 提问类型 */
149
+ agentTips: [
150
+ {
151
+ id: "default_analysis",
152
+ value: "整体分析",
153
+ content: "请对动力学计算结果进行整体分析",
154
+ type: "default_analysis"
155
+ }
156
+ ],
157
+ endpoints: {
158
+ createSession: "/ds-dynamics-alg-service/interpret/sessions",
159
+ listSessions: "/ds-dynamics-alg-service/interpret/sessions",
160
+ history: "/ds-dynamics-alg-service/interpret/history/:sessionId",
161
+ ask: "/ds-dynamics-alg-service/interpret/chat/ask",
162
+ cancel: "/ds-dynamics-alg-service/interpret/chat/cancel",
163
+ progress: "/ds-dynamics-alg-service/interpret/chat/progress"
164
+ }
165
+ };
166
+ },
167
+ computed: {
168
+ wellboreId() {
169
+ return String(this.$store?.state?.well?.wellboreId || "");
170
+ },
171
+ mainId() {
172
+ return String(this.$store?.state?.well?.mainId || "");
173
+ },
174
+ tripId() {
175
+ return String(this.$store?.state?.well?.tripId || "");
176
+ },
177
+ reloadKey() {
178
+ return `${this.wellboreId}|${this.mainId}|${this.tripId}`;
179
+ },
180
+ /**
181
+ * 各接口真实传参。
182
+ * - 主应用字段:在闭包里直接取(wellboreId 等)
183
+ * - 包内字段:用参数 runtime(sessionId / taskId / content / type / since)
184
+ */
185
+ requestParams() {
186
+ const self = this;
187
+ return {
188
+ createSession: () => ({
189
+ body: {
190
+ wellbore_id: self.wellboreId,
191
+ main_id: self.mainId,
192
+ trip_id: self.tripId
193
+ }
194
+ }),
195
+ listSessions: () => ({
196
+ query: {
197
+ wellbore_id: self.wellboreId,
198
+ main_id: self.mainId,
199
+ trip_id: self.tripId
200
+ }
201
+ }),
202
+ history: runtime => ({
203
+ path: { sessionId: runtime.sessionId }
204
+ }),
205
+ ask: runtime => ({
206
+ body: {
207
+ wellbore_id: self.wellboreId,
208
+ main_id: self.mainId,
209
+ trip_id: self.tripId,
210
+ session_id: runtime.sessionId,
211
+ type: runtime.type,
212
+ content: runtime.content
213
+ }
214
+ }),
215
+ cancel: runtime => ({
216
+ body: { task_id: runtime.taskId }
217
+ }),
218
+ progress: runtime => ({
219
+ query: {
220
+ task_id: runtime.taskId,
221
+ since: runtime.since
222
+ }
223
+ })
224
+ };
225
+ }
226
+ }
227
+ };
228
+ </script>
229
+ ```
230
+
231
+ 说明:
232
+
233
+ - 不必再传 `:context`;主应用字段写在 `requestParams` 闭包里即可。
234
+ - `endpoints` 已是完整路径(以 `/` 开头)时,不必再传 `base-url`。
235
+ - 宿主需已安装并注册 **Pinia**、**Element UI**。
236
+
237
+ ### 2.2 Props
238
+
239
+ | 模板属性 | 类型 | 说明 |
240
+ |----------|------|------|
241
+ | `request` | `AgentChatRequestFn` | 宿主请求函数(带 token)。不传则用 `fetch`(无鉴权) |
242
+ | `base-url` | `string` | 可选统一前缀。`endpoints` 已给完整路径时可省略。模板写 `base-url`(不要写成 `baseURL`) |
243
+ | `endpoints` | `AgentChatEndpoints` | 各接口路径。以 `/` 开头视为站点绝对路径,不再拼 `base-url` |
244
+ | `request-params` | `AgentChatRequestParams` | 各接口传参映射(主应用字段 + 包内 runtime) |
245
+ | `reload-key` | `string \| number` | 井/趟等维度变化时重拉会话。建议 `` `${wellboreId}|${mainId}|${tripId}` `` |
246
+ | `response-fields` | `AgentChatResponseFields` | 响应字段名。默认 `session_id` / `task_id` / `code === "OK"` |
247
+ | `theme` | `"light" \| "dark" \| "gray" \| "white"` | 面板主题;`white` 按 `light` 处理 |
248
+ | `tips` | `AgentChatTip[]` | 底部快捷提示(多项)。每项:`value` 文案、`content` 发送内容、`type` 提问类型。不传则用默认「整体分析」 |
249
+ | `show-open-in-browser` | `boolean` | 是否显示「浏览器打开」,默认 `true` |
250
+ | `poll-interval-ms` | `number` | 进度轮询间隔,默认 `500` |
251
+ | `context` | `AgentChatContext` | **已不推荐**。仅兼容旧写法;新接入请用 `request-params` |
252
+ | `required-context` | `string[]` | 仅在仍使用 `context` 时做必填校验 |
253
+
254
+ ### 2.3 Events
255
+
256
+ | 事件 | 说明 |
257
+ |------|------|
258
+ | `open-browser` | 点击「浏览器打开」。发送 / 切会话 / 取消由面板内部处理;新开页由宿主自行 `window.open` |
259
+
260
+ ### 2.4 `tips` 快捷提示
261
+
262
+ ```js
263
+ agentTips: [
264
+ {
265
+ id: "default_analysis",
266
+ value: "整体分析", // 按钮文案
267
+ content: "请对动力学计算结果进行整体分析", // 发送内容
268
+ type: "default_analysis" // ask.type
269
+ }
270
+ // 继续追加即可
271
+ ]
272
+ ```
273
+
274
+ 也可:
275
+
276
+ ```js
277
+ import { DEFAULT_AGENT_CHAT_TIPS } from "kd-chatbot-ui-vue2";
278
+ ```
279
+
280
+ ### 2.5 两套字段从哪里来
281
+
282
+ | 来源 | 例子 | 怎么写进请求 |
283
+ |------|------|----------------|
284
+ | **主应用** | `wellboreId`、`mainId`、`tripId` | 在 `requestParams` **闭包里直接取** |
285
+ | **包内 runtime** | `sessionId`、`taskId`、`content`、`type`、`since` | mapper 的参数 `runtime` |
286
+
287
+ `runtime` 由包在发请求前组装,宿主**不用**自己存 `sessionId`:
288
+
289
+ 1. 创建会话 / 拉列表后,包从响应读出 `session_id`(字段名可由 `response-fields` 改)
290
+ 2. 写入包内 store:`sessions[].id` + `activeId`
291
+ 3. 用户发送时取出当前会话 id,连同 `content`、`type` 放进 `runtime`
292
+ 4. 调用你写的 mapper,例如 `session_id: runtime.sessionId`
293
+
294
+ `taskId` 同理:来自 ask / history 响应,用于 cancel、progress。
295
+
296
+ ### 2.6 `requestParams` 返回结构
297
+
298
+ ```ts
299
+ type AgentChatParamMapper = (
300
+ runtime: AgentChatCallRuntime
301
+ ) => {
302
+ path?: Record<string, unknown>; // 替换 URL 里的 :name / {name}
303
+ query?: Record<string, unknown>; // GET 查询参数
304
+ body?: Record<string, unknown>; // POST body
305
+ };
306
+ ```
307
+
308
+ | 接口 key | 常用写法 |
309
+ |----------|----------|
310
+ | `createSession` | `body`:主应用隔离字段 |
311
+ | `listSessions` | `query`:主应用隔离字段 |
312
+ | `history` | `path: { sessionId: runtime.sessionId }` 填 `:sessionId` |
313
+ | `ask` | `body`:主应用字段 + `runtime.sessionId/type/content` |
314
+ | `cancel` | `body: { task_id: runtime.taskId }` |
315
+ | `progress` | `query: { task_id, since }` |
316
+
317
+ 只写需要改的接口;未写的接口仍走包内默认 interpret 字段。
318
+
319
+ ### 2.7 换项目时怎么改
320
+
321
+ **只换字段名:**
322
+
323
+ ```js
324
+ ask: runtime => ({
325
+ body: {
326
+ wellId: this.wellId, // 你们自己的主应用字段
327
+ chatId: runtime.sessionId, // 包内 sessionId → 你们的 chatId
328
+ msg: runtime.content
329
+ }
330
+ })
331
+ ```
332
+
333
+ **路径占位也不同:**
334
+
335
+ ```js
336
+ // endpoints
337
+ history: "/xxx/history/:conversationId"
338
+
339
+ // requestParams
340
+ history: runtime => ({
341
+ path: { conversationId: runtime.sessionId }
342
+ })
343
+ ```
344
+
345
+ **响应字段不同:**
346
+
347
+ ```vue
348
+ <AgentChatAdaptPanel
349
+ :response-fields="{ sessionId: 'id', taskId: 'taskId', okValue: 0 }"
350
+ ...
351
+ />
352
+ ```
353
+
354
+ 包读出后仍放入 `runtime.sessionId` / `runtime.taskId`,后续映射不变。
355
+
356
+ ### 2.8 `endpoints` 路径规则
357
+
358
+ - `http(s)://...`:原样使用
359
+ - 以 `/` 开头:站点绝对路径,**不拼** `base-url`
360
+ - 其它相对路径:拼在 `base-url` 后面
361
+ - `history` 支持 `:sessionId` 或 `{sessionId}`(或你在 `path` 里声明的其它占位名)
362
+
363
+ ### 2.9 约定接口(未覆盖 `endpoints` 时)
364
+
365
+ 相对 `base-url`:
366
+
367
+ | 方法 | 路径 | 说明 |
368
+ |------|------|------|
369
+ | `POST` | `/sessions` | 创建会话 |
370
+ | `GET` | `/sessions` | 会话列表 |
371
+ | `GET` | `/history/:sessionId` | 历史 |
372
+ | `POST` | `/chat/ask` | 提问(返回 `task_id`) |
373
+ | `POST` | `/chat/cancel` | 取消 |
374
+ | `GET` | `/chat/progress` | 轮询进度 |
375
+
376
+ 默认成功码:`code === "OK"`。
377
+
378
+ ---
379
+
380
+ ## 3. `AgentChatPanel`(受控模式)
381
+
382
+ 宿主自己调接口,用 props 传入展示数据;用户操作通过事件抛回宿主。
383
+
384
+ ### 3.1 Props / Events
385
+
386
+ | Props | 说明 |
387
+ |-------|------|
388
+ | `sessions` | `AgentSession[]` |
389
+ | `active-id` | 当前会话 id |
390
+ | `history-open` | 历史侧栏;用 **`:history-open.sync`**(不要用 `v-model:history-open`) |
391
+ | `is-replying` | 是否回复中 |
392
+ | `tips` / `theme` / `show-open-in-browser` | 同适配面板 |
393
+
394
+ | Events | 说明 |
395
+ |--------|------|
396
+ | `send` | `(payload: { text, type?, tip? })` |
397
+ | `select-session` | `(sessionId)` |
398
+ | `create-session` | 新建 |
399
+ | `cancel-reply` | 停止生成 |
400
+ | `clear-session` | 清空当前会话 |
401
+ | `update:historyOpen` | 切换历史栏(配合 `.sync`) |
402
+ | `open-browser` | 浏览器打开 |
403
+
404
+ ### 3.2 示例
405
+
406
+ ```vue
407
+ <template>
408
+ <AgentChatPanel
409
+ :sessions="sessions"
410
+ :active-id="activeId"
411
+ :history-open.sync="historyOpen"
412
+ :is-replying="isReplying"
413
+ @send="onSend"
414
+ @select-session="onSelect"
415
+ @create-session="onCreate"
416
+ @cancel-reply="onCancel"
417
+ @clear-session="onClear"
418
+ />
419
+ </template>
420
+
421
+ <script>
422
+ import { AgentChatPanel } from "kd-chatbot-ui-vue2";
423
+ import "kd-chatbot-ui-vue2/style.css";
424
+
425
+ export default {
426
+ components: { AgentChatPanel },
427
+ data() {
428
+ return {
429
+ sessions: [],
430
+ activeId: "",
431
+ historyOpen: false,
432
+ isReplying: false
433
+ };
434
+ },
435
+ methods: {
436
+ async onSend({ text, type }) {
437
+ this.isReplying = true;
438
+ // 调你们自己的接口,写入 sessions
439
+ this.isReplying = false;
440
+ },
441
+ onSelect(id) {
442
+ this.activeId = id;
443
+ },
444
+ onCreate() {},
445
+ onCancel() {},
446
+ onClear() {}
447
+ }
448
+ };
449
+ </script>
450
+ ```
451
+
452
+ ### 3.3 会话消息结构
453
+
454
+ ```ts
455
+ interface AgentSession {
456
+ id: string;
457
+ title: string;
458
+ content: AgentMessage[];
459
+ pinned?: boolean;
460
+ badge?: number;
461
+ updatedAt?: number;
462
+ snippet?: string;
463
+ }
464
+
465
+ interface AgentMessage {
466
+ type: "ask" | "answer";
467
+ placement: "start" | "end";
468
+ content: string;
469
+ segments?: { type: "reasoning" | "answer"; content: string }[];
470
+ }
471
+ ```
472
+
473
+ 流式回复:持续更新当前会话最后一条 `answer.segments`,再通过 `:sessions` 传入即可。
474
+
475
+ ---
476
+
477
+ ## 4. 导出一览
478
+
479
+ ```ts
480
+ import {
481
+ AgentChatAdaptPanel,
482
+ AgentChatPanel,
483
+ AgentChatView,
484
+ useAgentChat,
485
+ useAgentChatStore,
486
+ createAgentChatClient,
487
+ buildInterpretContext,
488
+ INTERPRET_POLL_INTERVAL_MS,
489
+ DEFAULT_AGENT_CHAT_TIPS
490
+ } from "kd-chatbot-ui-vue2";
491
+
492
+ import type {
493
+ AgentChatEndpoints,
494
+ AgentChatRequestParams,
495
+ AgentChatRequestFn,
496
+ AgentChatCallRuntime,
497
+ AgentChatResponseFields,
498
+ AgentChatContext,
499
+ AgentSession,
500
+ AgentMessage,
501
+ AgentChatTip,
502
+ AgentChatSendPayload,
503
+ AgentChatTheme
504
+ } from "kd-chatbot-ui-vue2";
505
+ ```
506
+
507
+ 默认导出为 Vue 插件:`Vue.use(KdChatbotUi)`。
508
+
509
+ ---
510
+
511
+ ## 5. 开发与发布
512
+
513
+ 本包在 Monorepo 内维护:
514
+
515
+ ```text
516
+ agent-chat-components/
517
+ packages/
518
+ kd-chatbot-ui/ # Vue3
519
+ kd-chatbot-ui-vue2/ # 本包
520
+ ```
521
+
522
+ ```bash
523
+ # 在 agent-chat-components 根目录
524
+ pnpm install
525
+ pnpm build:vue2 # 只构建本包
526
+ pnpm build # Vue2 + Vue3 都构建
527
+ pnpm dev:vue2 # watch 构建
528
+ ```
529
+
530
+ 构建产物:`dist/kd-chatbot-ui.js`、`dist/kd-chatbot-ui.css`、类型声明。
531
+
532
+ 发布(在本包目录或按你们的发包流程):
533
+
534
+ ```bash
535
+ pnpm --filter kd-chatbot-ui-vue2 publish
536
+ # prepublishOnly 会先执行 build
537
+ ```
538
+
539
+ ---
540
+
541
+ ## 6. 怎么选模式
542
+
543
+ - 后端仍是「会话 + ask + progress 轮询」,只是路径/字段名不同 → **`AgentChatAdaptPanel`** + `endpoints` + `requestParams`
544
+ - 协议完全不同,或宿主已有完整编排 → **`AgentChatPanel`**,自己管接口与 `sessions`
545
+
546
+ Vue 3 项目请用姊妹包 [`kd-chatbot-ui`](../kd-chatbot-ui),不要混用本包。
547
+
548
+ ---
549
+
550
+ ## 版本
551
+
552
+ - 包名:`kd-chatbot-ui-vue2`
553
+ - 版本:见本目录 `package.json` 的 `version`
554
+ - License:MIT