vue-element-ui-x 0.1.0

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.
Files changed (91) hide show
  1. package/README.md +47 -0
  2. package/lib/attachments.js +3046 -0
  3. package/lib/bubble-list.js +13845 -0
  4. package/lib/bubble.js +13130 -0
  5. package/lib/conversations.js +18817 -0
  6. package/lib/files-card.js +2457 -0
  7. package/lib/index.common.js +19 -0
  8. package/lib/index.esm.js +19 -0
  9. package/lib/index.js +38282 -0
  10. package/lib/index.umd.js +19 -0
  11. package/lib/mixins.js +1016 -0
  12. package/lib/prompts.js +832 -0
  13. package/lib/sender.js +1901 -0
  14. package/lib/think.js +799 -0
  15. package/lib/thinking.js +809 -0
  16. package/lib/thought-chain.js +30396 -0
  17. package/lib/typewriter.js +12793 -0
  18. package/lib/welcome.js +755 -0
  19. package/package.json +42 -0
  20. package/src/components/Attachments/index.js +8 -0
  21. package/src/components/Attachments/src/main.vue +537 -0
  22. package/src/components/Bubble/index.js +6 -0
  23. package/src/components/Bubble/src/main.vue +299 -0
  24. package/src/components/BubbleList/index.js +8 -0
  25. package/src/components/BubbleList/src/loading.vue +75 -0
  26. package/src/components/BubbleList/src/main.vue +466 -0
  27. package/src/components/Conversations/index.js +8 -0
  28. package/src/components/Conversations/src/components/item.vue +371 -0
  29. package/src/components/Conversations/src/main.vue +635 -0
  30. package/src/components/FilesCard/index.js +8 -0
  31. package/src/components/FilesCard/src/fileSvg/audio.vue +38 -0
  32. package/src/components/FilesCard/src/fileSvg/changeFileName.bat +18 -0
  33. package/src/components/FilesCard/src/fileSvg/code.vue +35 -0
  34. package/src/components/FilesCard/src/fileSvg/database.vue +94 -0
  35. package/src/components/FilesCard/src/fileSvg/excel.vue +38 -0
  36. package/src/components/FilesCard/src/fileSvg/file.vue +40 -0
  37. package/src/components/FilesCard/src/fileSvg/image.vue +40 -0
  38. package/src/components/FilesCard/src/fileSvg/index.js +46 -0
  39. package/src/components/FilesCard/src/fileSvg/link.vue +54 -0
  40. package/src/components/FilesCard/src/fileSvg/mark.vue +38 -0
  41. package/src/components/FilesCard/src/fileSvg/pdf.vue +38 -0
  42. package/src/components/FilesCard/src/fileSvg/ppt.vue +38 -0
  43. package/src/components/FilesCard/src/fileSvg/three.vue +38 -0
  44. package/src/components/FilesCard/src/fileSvg/txt.vue +38 -0
  45. package/src/components/FilesCard/src/fileSvg/unknown.vue +54 -0
  46. package/src/components/FilesCard/src/fileSvg/video.vue +38 -0
  47. package/src/components/FilesCard/src/fileSvg/word.vue +38 -0
  48. package/src/components/FilesCard/src/fileSvg/zip.vue +38 -0
  49. package/src/components/FilesCard/src/main.vue +405 -0
  50. package/src/components/FilesCard/src/options.js +18 -0
  51. package/src/components/Prompts/index.js +8 -0
  52. package/src/components/Prompts/src/main.vue +248 -0
  53. package/src/components/Sender/index.js +8 -0
  54. package/src/components/Sender/src/components/ClearButton.vue +28 -0
  55. package/src/components/Sender/src/components/Loading.vue +53 -0
  56. package/src/components/Sender/src/components/LoadingButton.vue +39 -0
  57. package/src/components/Sender/src/components/SendButton.vue +26 -0
  58. package/src/components/Sender/src/components/SpeechButton.vue +24 -0
  59. package/src/components/Sender/src/components/SpeechLoading.vue +87 -0
  60. package/src/components/Sender/src/components/SpeechLoadingButton.vue +43 -0
  61. package/src/components/Sender/src/main.vue +758 -0
  62. package/src/components/Think/index.js +8 -0
  63. package/src/components/Think/src/main.vue +190 -0
  64. package/src/components/Thinking/index.js +8 -0
  65. package/src/components/Thinking/src/main.vue +195 -0
  66. package/src/components/ThoughtChain/index.js +8 -0
  67. package/src/components/ThoughtChain/src/main.vue +293 -0
  68. package/src/components/Typewriter/index.js +8 -0
  69. package/src/components/Typewriter/src/main.vue +251 -0
  70. package/src/components/Welcome/index.js +8 -0
  71. package/src/components/Welcome/src/main.vue +151 -0
  72. package/src/index.js +63 -0
  73. package/src/mixins/index.js +49 -0
  74. package/src/mixins/recordMixin.js +118 -0
  75. package/src/mixins/sendMixin.js +357 -0
  76. package/src/mixins/streamMixin.js +499 -0
  77. package/src/styles/Attachments.scss +236 -0
  78. package/src/styles/Bubble.scss +157 -0
  79. package/src/styles/BubbleList.scss +148 -0
  80. package/src/styles/Conversations.scss +260 -0
  81. package/src/styles/FilesCard.scss +221 -0
  82. package/src/styles/Prompts.scss +195 -0
  83. package/src/styles/Sender.scss +199 -0
  84. package/src/styles/Think.scss +134 -0
  85. package/src/styles/Thinking.scss +112 -0
  86. package/src/styles/ThoughtChain.scss +113 -0
  87. package/src/styles/Typewriter.scss +66 -0
  88. package/src/styles/Welcome.scss +283 -0
  89. package/src/theme/var.scss +72 -0
  90. package/src/utils/index.js +199 -0
  91. package/src/utils/scrollDetector.js +34 -0
@@ -0,0 +1,499 @@
1
+ /**
2
+ * @fileoverview Vue2 流式数据处理 Mixin
3
+ * 从 Vue3 useXStream hooks 转换而来,支持 SSE 数据解析和中断功能
4
+ * @author Element UI X Team
5
+ * @version 1.0.0
6
+ */
7
+
8
+ /**
9
+ * 默认流分隔符
10
+ * @type {string}
11
+ * @constant
12
+ */
13
+ const DEFAULT_STREAM_SEPARATOR = '\n\n';
14
+
15
+ /**
16
+ * 默认部分分隔符
17
+ * @type {string}
18
+ * @constant
19
+ */
20
+ const DEFAULT_PART_SEPARATOR = '\n';
21
+
22
+ /**
23
+ * 默认键值分隔符
24
+ * @type {string}
25
+ * @constant
26
+ */
27
+ const DEFAULT_KV_SEPARATOR = ':';
28
+
29
+ /**
30
+ * SSE 字段类型定义
31
+ * @typedef {'data'|'event'|'id'|'retry'} SSEFields
32
+ */
33
+
34
+ /**
35
+ * SSE 输出对象类型
36
+ * @typedef {Object} SSEOutput
37
+ * @property {string} [data] - 数据字段
38
+ * @property {string} [event] - 事件字段
39
+ * @property {string} [id] - ID字段
40
+ * @property {string} [retry] - 重试字段
41
+ */
42
+
43
+ /**
44
+ * 流配置选项
45
+ * @typedef {Object} XStreamOptions
46
+ * @property {ReadableStream<Uint8Array>} readableStream - 可读流
47
+ * @property {TransformStream<string, *>} [transformStream] - 可选的转换流
48
+ */
49
+
50
+ /**
51
+ * 流状态对象
52
+ * @typedef {Object} StreamState
53
+ * @property {Array<*>} data - 流数据数组
54
+ * @property {Error|null} error - 错误信息
55
+ * @property {boolean} loading - 加载状态
56
+ */
57
+
58
+ /**
59
+ * 流回调函数配置
60
+ * @typedef {Object} StreamCallbacks
61
+ * @property {function(*): void} [onData] - 数据回调函数
62
+ * @property {function(Array<*>): void} [onComplete] - 完成回调函数
63
+ * @property {function(Error): void} [onError] - 错误回调函数
64
+ * @property {function(): void} [onCancel] - 取消回调函数
65
+ * @property {function(): void} [onFinish] - 结束回调函数
66
+ */
67
+
68
+ /**
69
+ * 流工具函数返回对象
70
+ * @typedef {Object} StreamUtils
71
+ * @property {StreamState} state - 流状态
72
+ * @property {function(XStreamOptions): Promise<void>} startStream - 启动流处理
73
+ * @property {function(): void} cancel - 取消流处理
74
+ * @property {function(): void} reset - 重置流状态
75
+ */
76
+
77
+ /**
78
+ * 验证字符串是否有效(非空且非空白)
79
+ * @param {string} str - 待验证的字符串
80
+ * @returns {boolean} 是否为有效字符串
81
+ */
82
+ const isValidString = str => (str === null || str === undefined ? '' : str).trim() !== '';
83
+
84
+ /**
85
+ * 创建流分割转换器
86
+ * 按照默认分隔符分割流数据
87
+ * @returns {TransformStream<string, string>} 流分割转换器
88
+ */
89
+ function splitStream() {
90
+ let buffer = '';
91
+
92
+ return new TransformStream({
93
+ /**
94
+ * 转换函数
95
+ * @param {string} chunk - 数据块
96
+ * @param {TransformStreamDefaultController<string>} controller - 控制器
97
+ */
98
+ transform(chunk, controller) {
99
+ buffer += chunk;
100
+ const parts = buffer.split(DEFAULT_STREAM_SEPARATOR);
101
+ parts.slice(0, -1).forEach(part => {
102
+ if (isValidString(part)) controller.enqueue(part);
103
+ });
104
+ buffer = parts[parts.length - 1];
105
+ },
106
+ /**
107
+ * 刷新函数
108
+ * @param {TransformStreamDefaultController<string>} controller - 控制器
109
+ */
110
+ flush(controller) {
111
+ if (isValidString(buffer)) controller.enqueue(buffer);
112
+ },
113
+ });
114
+ }
115
+
116
+ /**
117
+ * 创建 SSE 数据解析转换器
118
+ * 将文本数据解析为 SSE 格式对象
119
+ * @returns {TransformStream<string, SSEOutput>} SSE 解析转换器
120
+ */
121
+ function splitPart() {
122
+ return new TransformStream({
123
+ /**
124
+ * 转换函数
125
+ * @param {string} partChunk - 数据块
126
+ * @param {TransformStreamDefaultController<SSEOutput>} controller - 控制器
127
+ */
128
+ transform(partChunk, controller) {
129
+ const lines = partChunk.split(DEFAULT_PART_SEPARATOR);
130
+ const sseEvent = lines.reduce((acc, line) => {
131
+ const sepIndex = line.indexOf(DEFAULT_KV_SEPARATOR);
132
+ if (sepIndex === -1) return acc;
133
+
134
+ const key = line.slice(0, sepIndex);
135
+ if (!isValidString(key)) return acc;
136
+
137
+ const value = line.slice(sepIndex + 1);
138
+ return {
139
+ ...acc,
140
+ [key]: value,
141
+ };
142
+ }, {});
143
+
144
+ if (Object.keys(sseEvent).length > 0) controller.enqueue(sseEvent);
145
+ },
146
+ });
147
+ }
148
+
149
+ /**
150
+ * 核心流处理函数(支持中断)
151
+ * @param {XStreamOptions} options - 配置选项
152
+ * @param {ReadableStream<Uint8Array>} options.readableStream - 可读流
153
+ * @param {TransformStream<string, *>} [options.transformStream] - 可选的转换流
154
+ * @param {AbortSignal} [signal] - 中断信号
155
+ * @returns {ReadableStream<*>} 处理后的流,支持异步迭代
156
+ * @throws {TypeError} 当 readableStream 不是 ReadableStream 实例时抛出
157
+ */
158
+ function XStream(options, signal) {
159
+ const { readableStream, transformStream } = options;
160
+ if (!(readableStream instanceof ReadableStream)) {
161
+ throw new TypeError('options.readableStream 必须是 ReadableStream 的实例。');
162
+ }
163
+
164
+ const decoderStream = new TextDecoderStream();
165
+ const processedStream = transformStream
166
+ ? readableStream.pipeThrough(decoderStream).pipeThrough(transformStream)
167
+ : readableStream.pipeThrough(decoderStream).pipeThrough(splitStream()).pipeThrough(splitPart());
168
+
169
+ // 为流添加异步迭代器并处理中断信号
170
+ processedStream[Symbol.asyncIterator] = async function* () {
171
+ const reader = this.getReader();
172
+ this.reader = reader; // 保存读取器引用
173
+ try {
174
+ while (true) {
175
+ if (signal && signal.aborted) {
176
+ await reader.cancel(); // 主动取消 reader
177
+ break;
178
+ }
179
+ const { done, value } = await reader.read();
180
+ if (done) break;
181
+ if (value) yield value;
182
+ }
183
+ } finally {
184
+ reader.releaseLock(); // 释放锁
185
+ }
186
+ };
187
+
188
+ return processedStream;
189
+ }
190
+
191
+ /**
192
+ * streamMixin - Vue2 版本
193
+ * 用于处理流式数据的 mixin,支持 SSE 数据解析和中断功能
194
+ * @namespace streamMixin
195
+ * @type {Object}
196
+ */
197
+ export const streamMixin = {
198
+ /**
199
+ * 组件数据
200
+ * @returns {Object} 响应式数据对象
201
+ * @property {Array<*>} streamData - 流数据数组
202
+ * @property {Error|null} streamError - 流错误信息
203
+ * @property {boolean} streamLoading - 流处理状态
204
+ * @property {AbortController|null} _abortController - 私有:中断控制器
205
+ * @property {ReadableStream|null} _currentStream - 私有:当前流引用
206
+ */
207
+ data() {
208
+ return {
209
+ streamData: [],
210
+ streamError: null,
211
+ streamLoading: false,
212
+ _abortController: null,
213
+ _currentStream: null,
214
+ };
215
+ },
216
+
217
+ methods: {
218
+ /**
219
+ * 启动流式请求
220
+ * @async
221
+ * @param {XStreamOptions} options - 流配置选项
222
+ * @param {ReadableStream<Uint8Array>} options.readableStream - 可读流
223
+ * @param {TransformStream<string, *>} [options.transformStream] - 可选的转换流
224
+ * @returns {Promise<void>} 流处理完成的 Promise
225
+ * @fires streamMixin#stream-data - 收到新数据时触发
226
+ * @fires streamMixin#stream-complete - 流完成时触发
227
+ * @fires streamMixin#stream-error - 流错误时触发
228
+ * @fires streamMixin#stream-finish - 流处理结束时触发
229
+ * @example
230
+ * // 基础使用
231
+ * const response = await fetch('/api/stream')
232
+ * await this.startStream({ readableStream: response.body })
233
+ *
234
+ * // 使用自定义转换流
235
+ * const customTransform = new TransformStream({ ... })
236
+ * await this.startStream({
237
+ * readableStream: response.body,
238
+ * transformStream: customTransform
239
+ * })
240
+ */
241
+ async startStream(options) {
242
+ this.streamLoading = true;
243
+ this.streamError = null;
244
+ this.streamData = [];
245
+ this._abortController = new AbortController();
246
+ this._currentStream = XStream(options, this._abortController.signal);
247
+
248
+ try {
249
+ for await (const item of this._currentStream) {
250
+ this.streamData.push(item);
251
+ // 触发数据更新事件
252
+ /**
253
+ * 流数据事件
254
+ * @event streamMixin#stream-data
255
+ * @type {*} 流数据项
256
+ */
257
+ this.$emit('stream-data', item);
258
+ }
259
+ // 流完成事件
260
+ /**
261
+ * 流完成事件
262
+ * @event streamMixin#stream-complete
263
+ * @type {Array<*>} 所有流数据
264
+ */
265
+ this.$emit('stream-complete', this.streamData);
266
+ } catch (err) {
267
+ if (err instanceof Error) {
268
+ this.streamError = err;
269
+ /**
270
+ * 流错误事件
271
+ * @event streamMixin#stream-error
272
+ * @type {Error} 错误对象
273
+ */
274
+ this.$emit('stream-error', err);
275
+ }
276
+ } finally {
277
+ this.streamLoading = false;
278
+ this._currentStream = null; // 释放流引用
279
+ this._abortController = null; // 释放控制器
280
+ /**
281
+ * 流处理结束事件
282
+ * @event streamMixin#stream-finish
283
+ */
284
+ this.$emit('stream-finish');
285
+ }
286
+ },
287
+
288
+ /**
289
+ * 中断流式请求(强制关闭流)
290
+ * @returns {void}
291
+ * @fires streamMixin#stream-cancel - 流被中断时触发
292
+ * @example
293
+ * this.cancelStream()
294
+ */
295
+ cancelStream() {
296
+ if (this._abortController) {
297
+ this._abortController.abort();
298
+ /**
299
+ * 流取消事件
300
+ * @event streamMixin#stream-cancel
301
+ */
302
+ this.$emit('stream-cancel');
303
+ }
304
+ },
305
+
306
+ /**
307
+ * 重置流状态
308
+ * 清空所有数据和状态,但不触发事件
309
+ * @returns {void}
310
+ * @example
311
+ * this.resetStream()
312
+ */
313
+ resetStream() {
314
+ this.streamData = [];
315
+ this.streamError = null;
316
+ this.streamLoading = false;
317
+ this._abortController = null;
318
+ this._currentStream = null;
319
+ },
320
+
321
+ /**
322
+ * 创建流处理器的便捷方法
323
+ * @param {ReadableStream<Uint8Array>} readableStream - 可读流
324
+ * @param {TransformStream<string, *>} [transformStream] - 可选的转换流
325
+ * @returns {XStreamOptions} 流处理器配置对象
326
+ * @example
327
+ * const processor = this.createStreamProcessor(response.body)
328
+ * await this.startStream(processor)
329
+ */
330
+ createStreamProcessor(readableStream, transformStream) {
331
+ return {
332
+ readableStream,
333
+ transformStream,
334
+ };
335
+ },
336
+ },
337
+
338
+ /**
339
+ * 组件销毁前的生命周期钩子
340
+ * 自动清理流资源
341
+ * @returns {void}
342
+ */
343
+ beforeDestroy() {
344
+ // 组件销毁时清理资源
345
+ this.cancelStream();
346
+ },
347
+ };
348
+
349
+ /**
350
+ * 工具函数版本 - 用于非组件场景
351
+ * @param {StreamCallbacks} [callbacks={}] - 回调函数配置
352
+ * @param {function(*): void} [callbacks.onData] - 数据回调函数
353
+ * @param {function(Array<*>): void} [callbacks.onComplete] - 完成回调函数
354
+ * @param {function(Error): void} [callbacks.onError] - 错误回调函数
355
+ * @param {function(): void} [callbacks.onCancel] - 取消回调函数
356
+ * @param {function(): void} [callbacks.onFinish] - 结束回调函数
357
+ * @returns {StreamUtils} 包含流处理相关方法的对象
358
+ * @example
359
+ * // 基础使用
360
+ * const streamUtils = createStreamUtils({
361
+ * onData: (item) => console.log('数据:', item),
362
+ * onComplete: (allData) => console.log('完成:', allData),
363
+ * onError: (error) => console.error('错误:', error)
364
+ * })
365
+ *
366
+ * const response = await fetch('/api/stream')
367
+ * await streamUtils.startStream({ readableStream: response.body })
368
+ */
369
+ export function createStreamUtils(callbacks = {}) {
370
+ /**
371
+ * 流状态对象
372
+ * @type {StreamState}
373
+ */
374
+ const state = {
375
+ data: [],
376
+ error: null,
377
+ loading: false,
378
+ };
379
+
380
+ let abortController = null;
381
+ let currentStream = null;
382
+
383
+ /**
384
+ * 启动流处理
385
+ * @async
386
+ * @param {XStreamOptions} options - 流配置选项
387
+ * @returns {Promise<void>} 流处理完成的 Promise
388
+ */
389
+ const startStream = async options => {
390
+ state.loading = true;
391
+ state.error = null;
392
+ state.data = [];
393
+ abortController = new AbortController();
394
+ currentStream = XStream(options, abortController.signal);
395
+
396
+ try {
397
+ for await (const item of currentStream) {
398
+ state.data.push(item);
399
+ if (callbacks.onData) {
400
+ callbacks.onData(item);
401
+ }
402
+ }
403
+ if (callbacks.onComplete) {
404
+ callbacks.onComplete(state.data);
405
+ }
406
+ } catch (err) {
407
+ if (err instanceof Error) {
408
+ state.error = err;
409
+ if (callbacks.onError) {
410
+ callbacks.onError(err);
411
+ }
412
+ }
413
+ } finally {
414
+ state.loading = false;
415
+ currentStream = null;
416
+ abortController = null;
417
+ if (callbacks.onFinish) {
418
+ callbacks.onFinish();
419
+ }
420
+ }
421
+ };
422
+
423
+ /**
424
+ * 取消流处理
425
+ * @returns {void}
426
+ */
427
+ const cancel = () => {
428
+ if (abortController) {
429
+ abortController.abort();
430
+ if (callbacks.onCancel) {
431
+ callbacks.onCancel();
432
+ }
433
+ }
434
+ };
435
+
436
+ /**
437
+ * 重置流状态
438
+ * @returns {void}
439
+ */
440
+ const reset = () => {
441
+ state.data = [];
442
+ state.error = null;
443
+ state.loading = false;
444
+ abortController = null;
445
+ currentStream = null;
446
+ };
447
+
448
+ return {
449
+ state,
450
+ startStream,
451
+ cancel,
452
+ reset,
453
+ };
454
+ }
455
+
456
+ // 导出常量和工具函数
457
+ export {
458
+ /**
459
+ * 默认键值分隔符
460
+ * @type {string}
461
+ */
462
+ DEFAULT_KV_SEPARATOR,
463
+ /**
464
+ * 默认部分分隔符
465
+ * @type {string}
466
+ */
467
+ DEFAULT_PART_SEPARATOR,
468
+ /**
469
+ * 默认流分隔符
470
+ * @type {string}
471
+ */
472
+ DEFAULT_STREAM_SEPARATOR,
473
+ /**
474
+ * 字符串验证函数
475
+ * @type {function(string): boolean}
476
+ */
477
+ isValidString,
478
+ /**
479
+ * SSE 数据解析转换器
480
+ * @type {function(): TransformStream<string, SSEOutput>}
481
+ */
482
+ splitPart,
483
+ /**
484
+ * 流分割转换器
485
+ * @type {function(): TransformStream<string, string>}
486
+ */
487
+ splitStream,
488
+ /**
489
+ * 核心流处理函数
490
+ * @type {function(XStreamOptions, AbortSignal=): ReadableStream}
491
+ */
492
+ XStream,
493
+ };
494
+
495
+ /**
496
+ * 默认导出 streamMixin
497
+ * @type {Object}
498
+ */
499
+ export default streamMixin;