@szjy/ai-coms 0.1.10 → 0.1.12

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.
@@ -27,7 +27,7 @@ export interface VoiceManagerOptions {
27
27
  onProgress?: (info: VoiceProgressInfo) => void;
28
28
  onVolumeChange?: (volume: number) => void;
29
29
  onAudioRecorded?: (audioUrl: string, blob: Blob) => void;
30
- /** 流式中间文本(已确认分片 + 当前分片正在生成的字) */
30
+ /** 转写过程中的中间文本(录音结束后 / 上传文件时按 token 回推) */
31
31
  onPartial?: (text: string) => void;
32
32
  onResult?: (text: string) => void;
33
33
  onError?: (error: string) => void;
@@ -44,13 +44,8 @@ export declare class VoiceInputManager {
44
44
  private currentTaskId;
45
45
  private pcmParts;
46
46
  private pcmLength;
47
- private pcmSent;
48
- private streamBusy;
49
- private streamFinalPending;
50
47
  private streamChunkIndex;
51
48
  private committedText;
52
- private chunkPartialText;
53
- private streamPumpTimer;
54
49
  constructor(options?: VoiceManagerOptions);
55
50
  get currentStatus(): VoiceStatus;
56
51
  get ready(): boolean;
@@ -59,7 +54,7 @@ export declare class VoiceInputManager {
59
54
  */
60
55
  init(customBaseUrl?: string): Promise<void>;
61
56
  /**
62
- * 开始语音录入
57
+ * 开始语音录入(只采集,点「完成」后再转写)
63
58
  */
64
59
  startRecording(): Promise<void>;
65
60
  /**
@@ -90,20 +85,15 @@ export declare class VoiceInputManager {
90
85
  * 销毁并释放所有资源
91
86
  */
92
87
  destroy(): void;
93
- private startStreamPump;
94
- private stopStreamPump;
95
- private getNextChunkSize;
96
88
  private resetStreamState;
97
89
  private appendPcm;
98
90
  private mergePcm;
99
- private copyPcm;
100
- private emitLiveText;
91
+ private emitPartial;
101
92
  private finishStream;
102
93
  /**
103
- * 将未发送的 PCM 按固定窗口送给 Worker。
104
- * isFinal=true 表示采集已结束,发完剩余尾巴后收口。
94
+ * 录音结束或上传:整段一次送入 Worker。超过 30s 由 Worker 按重叠窗口切分。
105
95
  */
106
- private tryDispatchStreamChunk;
96
+ private dispatchFullAudio;
107
97
  private handleWorkerMessage;
108
98
  private setStatus;
109
99
  }
@@ -1,3 +1,3 @@
1
- declare let MarkdownInstance: null;
2
- export declare function genMarkdownIt(): null;
1
+ declare let MarkdownInstance: MarkdownItInstance | null;
2
+ export declare function genMarkdownIt(): MarkdownItInstance | null;
3
3
  export { MarkdownInstance };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 聊天运行时依赖加载(markdown-it / highlight.js)
3
+ * 挂件(sz-ai-chat)与嵌入式(sz-ai-chat-plain)两种外壳共用:
4
+ * 从 /scripts/ai/ 加载 markdown-it 与 highlight 脚本,完成后初始化全局 MarkdownIt 实例。
5
+ */
6
+ export declare function useChatDeps(): void;
@@ -56,6 +56,20 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
56
56
  type: StringConstructor;
57
57
  default: string;
58
58
  };
59
+ /**
60
+ * 是否显示麦克风语音输入入口,默认关闭
61
+ */
62
+ enableVoiceInput: {
63
+ type: BooleanConstructor;
64
+ default: boolean;
65
+ };
66
+ /**
67
+ * 是否显示上传音频/视频识别入口,默认关闭
68
+ */
69
+ enableVoiceUpload: {
70
+ type: BooleanConstructor;
71
+ default: boolean;
72
+ };
59
73
  }>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
60
74
  token: {
61
75
  type: StringConstructor;
@@ -114,15 +128,31 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
114
128
  type: StringConstructor;
115
129
  default: string;
116
130
  };
131
+ /**
132
+ * 是否显示麦克风语音输入入口,默认关闭
133
+ */
134
+ enableVoiceInput: {
135
+ type: BooleanConstructor;
136
+ default: boolean;
137
+ };
138
+ /**
139
+ * 是否显示上传音频/视频识别入口,默认关闭
140
+ */
141
+ enableVoiceUpload: {
142
+ type: BooleanConstructor;
143
+ default: boolean;
144
+ };
117
145
  }>> & Readonly<{}>, {
146
+ baseUrl: string;
118
147
  token: string;
119
148
  identifier: string;
120
- baseUrl: string;
121
149
  title: string;
122
150
  llmName: string;
123
151
  messagePostRender: Function;
124
152
  extraConfig: Record<string, any>;
125
153
  soundBaseUrl: string;
126
154
  workerUrl: string;
155
+ enableVoiceInput: boolean;
156
+ enableVoiceUpload: boolean;
127
157
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
128
158
  export default _default;
@@ -5,6 +5,18 @@ import { createSparkStylized } from '../../../../api/ai';
5
5
  * 如: 科大讯飞星火、Kimi Moonshot 等大模型的 response
6
6
  */
7
7
  export declare const parseJsonLikeData: (content: any) => any;
8
+ /**
9
+ * 从大模型原始输出中分离「思考过程」与「正文」,兼容两种格式:
10
+ * 1. 标准 <think>...</think> 包裹(DeepSeek R1 风格)
11
+ * 2. Dify 兼容口:思考内容直接输出在前,仅以 </think> 结尾(无开标签)
12
+ *
13
+ * isThinkingStreaming 表示流式输出尚未闭合(已出现 <think> 但还没等到 </think>)。
14
+ */
15
+ export declare const parseThinking: (raw: string) => {
16
+ thinking: string;
17
+ content: string;
18
+ isThinkingStreaming: boolean;
19
+ };
8
20
  /**
9
21
  * 大模型映射列表
10
22
  */
@@ -0,0 +1,3 @@
1
+ import { default as SzAiChatPlain } from './src/index.vue';
2
+
3
+ export { SzAiChatPlain };
@@ -0,0 +1,162 @@
1
+ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
2
+ token: {
3
+ type: StringConstructor;
4
+ default: string;
5
+ };
6
+ identifier: {
7
+ type: StringConstructor;
8
+ default: string;
9
+ };
10
+ baseUrl: {
11
+ type: StringConstructor;
12
+ default: string;
13
+ };
14
+ title: {
15
+ type: StringConstructor;
16
+ default: string;
17
+ };
18
+ /**
19
+ * 大模型名称,对应 LLMTypes 中的 modelName
20
+ * 例如: 'szjy' | 'spark' | 'dify-openai' | 'siliconflow' 等
21
+ * 默认使用 'szjy'
22
+ */
23
+ llmName: {
24
+ type: StringConstructor;
25
+ default: string;
26
+ };
27
+ /**
28
+ * 消息后处理回调函数
29
+ * 在 AI 消息渲染完成后调用,可用于自定义处理渲染后的内容
30
+ * @param container - 消息容器的 DOM 元素
31
+ * @param textContent - 消息的文本内容
32
+ */
33
+ messagePostRender: {
34
+ type: FunctionConstructor;
35
+ default: null;
36
+ };
37
+ /**
38
+ * 额外配置参数,用于扩展供应商 API 调用
39
+ * 例如:{ projectId: 'xxx' } 供 Dify 等供应商使用
40
+ */
41
+ extraConfig: {
42
+ type: ObjectConstructor;
43
+ default: () => {};
44
+ };
45
+ /**
46
+ * 语音识别模型静态资源基础路径,默认为 '/sounds/'
47
+ */
48
+ soundBaseUrl: {
49
+ type: StringConstructor;
50
+ default: string;
51
+ };
52
+ /**
53
+ * Whisper Worker 脚本地址。不传则自动探测库产物与 /scripts/ai/whisper.worker.js
54
+ */
55
+ workerUrl: {
56
+ type: StringConstructor;
57
+ default: string;
58
+ };
59
+ /**
60
+ * 是否显示麦克风语音输入入口,默认关闭
61
+ */
62
+ enableVoiceInput: {
63
+ type: BooleanConstructor;
64
+ default: boolean;
65
+ };
66
+ /**
67
+ * 是否显示上传音频/视频识别入口,默认关闭
68
+ */
69
+ enableVoiceUpload: {
70
+ type: BooleanConstructor;
71
+ default: boolean;
72
+ };
73
+ }>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
74
+ submit: (...args: any[]) => void;
75
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
76
+ token: {
77
+ type: StringConstructor;
78
+ default: string;
79
+ };
80
+ identifier: {
81
+ type: StringConstructor;
82
+ default: string;
83
+ };
84
+ baseUrl: {
85
+ type: StringConstructor;
86
+ default: string;
87
+ };
88
+ title: {
89
+ type: StringConstructor;
90
+ default: string;
91
+ };
92
+ /**
93
+ * 大模型名称,对应 LLMTypes 中的 modelName
94
+ * 例如: 'szjy' | 'spark' | 'dify-openai' | 'siliconflow' 等
95
+ * 默认使用 'szjy'
96
+ */
97
+ llmName: {
98
+ type: StringConstructor;
99
+ default: string;
100
+ };
101
+ /**
102
+ * 消息后处理回调函数
103
+ * 在 AI 消息渲染完成后调用,可用于自定义处理渲染后的内容
104
+ * @param container - 消息容器的 DOM 元素
105
+ * @param textContent - 消息的文本内容
106
+ */
107
+ messagePostRender: {
108
+ type: FunctionConstructor;
109
+ default: null;
110
+ };
111
+ /**
112
+ * 额外配置参数,用于扩展供应商 API 调用
113
+ * 例如:{ projectId: 'xxx' } 供 Dify 等供应商使用
114
+ */
115
+ extraConfig: {
116
+ type: ObjectConstructor;
117
+ default: () => {};
118
+ };
119
+ /**
120
+ * 语音识别模型静态资源基础路径,默认为 '/sounds/'
121
+ */
122
+ soundBaseUrl: {
123
+ type: StringConstructor;
124
+ default: string;
125
+ };
126
+ /**
127
+ * Whisper Worker 脚本地址。不传则自动探测库产物与 /scripts/ai/whisper.worker.js
128
+ */
129
+ workerUrl: {
130
+ type: StringConstructor;
131
+ default: string;
132
+ };
133
+ /**
134
+ * 是否显示麦克风语音输入入口,默认关闭
135
+ */
136
+ enableVoiceInput: {
137
+ type: BooleanConstructor;
138
+ default: boolean;
139
+ };
140
+ /**
141
+ * 是否显示上传音频/视频识别入口,默认关闭
142
+ */
143
+ enableVoiceUpload: {
144
+ type: BooleanConstructor;
145
+ default: boolean;
146
+ };
147
+ }>> & Readonly<{
148
+ onSubmit?: ((...args: any[]) => any) | undefined;
149
+ }>, {
150
+ baseUrl: string;
151
+ token: string;
152
+ identifier: string;
153
+ title: string;
154
+ llmName: string;
155
+ messagePostRender: Function;
156
+ extraConfig: Record<string, any>;
157
+ soundBaseUrl: string;
158
+ workerUrl: string;
159
+ enableVoiceInput: boolean;
160
+ enableVoiceUpload: boolean;
161
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
162
+ export default _default;
@@ -1 +1,2 @@
1
1
  export * from './AiChat/index';
2
+ export * from './AiChatPlain/index';
@@ -6,9 +6,16 @@
6
6
  | :--- | ---: | :--- | :--- |
7
7
  | `whisper.worker.js` | ~10 KB | 可以 | 改 `whisper.worker.ts` 协议时 |
8
8
  | `transformers.runtime.js` | ~56 MB | 否 | 升级 `@huggingface/transformers` |
9
+ | `ort-wasm-simd-threaded.jsep.mjs` | ~45 KB | 否 | 随 onnxruntime-web 升级 |
10
+ | `ort-wasm-simd-threaded.jsep.wasm` | ~21 MB | 否 | 随 onnxruntime-web 升级 |
9
11
 
10
- 日常改识别协议只提交 / 重拷 `whisper.worker.js`。大运行时请加入宿主 `.gitignore`:
12
+ 日常改识别协议只提交 / 重拷 `whisper.worker.js`。大运行时与 ORT WASM 请加入宿主 `.gitignore`:
11
13
 
12
14
  ```
13
15
  public/scripts/ai/transformers.runtime.js
16
+ public/scripts/ai/ort-wasm*
17
+ public/scripts/ai/*.wasm
14
18
  ```
19
+
20
+ `pnpm build:voice` / `pnpm dev` 会从 `node_modules/onnxruntime-web/dist` 自动同步 `ort-wasm*` 到本目录。缺这些文件时控制台会出现:
21
+ `no available backend found ... ort-wasm-simd-threaded.jsep.mjs`。
@@ -35,6 +35,51 @@ async function clearVoiceModelCache(dirName = DEFAULT_CACHE_DIR) {
35
35
  }
36
36
  return cleared;
37
37
  }
38
+ const PURE_HALLUCINATION = [
39
+ /^(谢谢(观看|收看)?|感謝觀看|感谢观看)[。.!!]*$/u,
40
+ /^(thank you( for watching)?|thanks for watching)[。.!!]*$/i,
41
+ /^(字幕(by|志愿者|組|组)?|subscribe|订阅|訂閱)[。.!!]*$/iu,
42
+ /^(请不吝点赞|請不吝點贊).*$/u,
43
+ /^(三十分|三十秒|三十分钟|三十分鐘)[。.!!]*$/u
44
+ ];
45
+ function collapseRepeatedPhrases(text) {
46
+ if (!text) return "";
47
+ let s = text.replace(/[ \t]+/g, " ").replace(/([一-龥])\s+(?=[一-龥])/g, "$1").trim();
48
+ if (!s) return "";
49
+ let prev = "";
50
+ let guard = 0;
51
+ while (s !== prev && guard++ < 12) {
52
+ prev = s;
53
+ for (let len = 12; len >= 2; len--) {
54
+ const re = new RegExp(`(.{${len}})\\1+`, "g");
55
+ s = s.replace(re, "$1");
56
+ }
57
+ s = s.replace(/(.)\1{3,}/g, "$1$1");
58
+ }
59
+ return s.trim();
60
+ }
61
+ function isPureHallucination(text) {
62
+ const t = text.trim();
63
+ if (!t) return true;
64
+ return PURE_HALLUCINATION.some((re) => re.test(t));
65
+ }
66
+ function clampTranscriptToAudio(text, durationSec) {
67
+ if (!text) return "";
68
+ const maxChars = Math.max(16, Math.round(Math.max(0, durationSec) * 8) + 12);
69
+ if (text.length <= maxChars) return text;
70
+ return text.slice(0, maxChars).trim();
71
+ }
72
+ function sanitizeTranscript(text, durationSec = 0) {
73
+ let cleaned = collapseRepeatedPhrases(text || "");
74
+ if (!cleaned) return "";
75
+ if (isPureHallucination(cleaned)) return "";
76
+ if (durationSec > 0) {
77
+ cleaned = clampTranscriptToAudio(cleaned, durationSec);
78
+ cleaned = collapseRepeatedPhrases(cleaned);
79
+ if (isPureHallucination(cleaned)) return "";
80
+ }
81
+ return cleaned;
82
+ }
38
83
  if (env?.backends?.onnx?.wasm) {
39
84
  env.backends.onnx.wasm.wasmPaths = new URL(
40
85
  /* @vite-ignore */
@@ -46,6 +91,7 @@ let asrPipeline = null;
46
91
  let isInitializing = false;
47
92
  let transcribeQueue = [];
48
93
  let transcribeRunning = false;
94
+ const cancelledTaskIds = /* @__PURE__ */ new Set();
49
95
  const originalFetch = self.fetch.bind(self);
50
96
  self.fetch = async (input, init) => {
51
97
  const response = await originalFetch(input, init);
@@ -71,6 +117,16 @@ self.addEventListener("message", async (e) => {
71
117
  case "TRANSCRIBE":
72
118
  await enqueueTranscribe(data);
73
119
  break;
120
+ case "CANCEL":
121
+ if (typeof data?.taskId === "number") {
122
+ cancelledTaskIds.add(data.taskId);
123
+ if (cancelledTaskIds.size > 24) {
124
+ const first = cancelledTaskIds.values().next().value;
125
+ if (typeof first === "number") cancelledTaskIds.delete(first);
126
+ }
127
+ transcribeQueue = transcribeQueue.filter((item) => item?.taskId !== data.taskId);
128
+ }
129
+ break;
74
130
  case "CLEAR_CACHE":
75
131
  try {
76
132
  await clearVoiceModelCache();
@@ -195,22 +251,31 @@ async function initPipeline(config) {
195
251
  }
196
252
  }
197
253
  async function enqueueTranscribe(data) {
254
+ if (typeof data?.taskId === "number" && cancelledTaskIds.has(data.taskId)) {
255
+ return;
256
+ }
198
257
  transcribeQueue.push(data);
199
258
  if (transcribeRunning) return;
200
259
  transcribeRunning = true;
201
260
  while (transcribeQueue.length) {
202
261
  const next = transcribeQueue.shift();
262
+ if (typeof next?.taskId === "number" && cancelledTaskIds.has(next.taskId)) {
263
+ continue;
264
+ }
203
265
  await transcribeAudio(next);
204
266
  }
205
267
  transcribeRunning = false;
206
268
  }
207
- function getPeakAmplitude(audio) {
208
- let maxVal = 0;
269
+ function getAudioStats(audio) {
270
+ let peak = 0;
271
+ let sumSq = 0;
209
272
  for (let i = 0; i < audio.length; i++) {
210
- const abs = Math.abs(audio[i]);
211
- if (abs > maxVal) maxVal = abs;
273
+ const sample = audio[i];
274
+ const abs = Math.abs(sample);
275
+ if (abs > peak) peak = abs;
276
+ sumSq += sample * sample;
212
277
  }
213
- return maxVal;
278
+ return { peak, rms: Math.sqrt(sumSq / Math.max(1, audio.length)) };
214
279
  }
215
280
  async function transcribeAudio(data) {
216
281
  if (!asrPipeline) {
@@ -227,33 +292,52 @@ async function transcribeAudio(data) {
227
292
  language = "chinese",
228
293
  task = "transcribe",
229
294
  chunkIndex = 0,
230
- isFinal = true
295
+ isFinal = true,
296
+ mode = "append",
297
+ nativeChunking = false
231
298
  } = data;
299
+ if (typeof taskId === "number" && cancelledTaskIds.has(taskId)) {
300
+ return;
301
+ }
232
302
  try {
233
303
  self.postMessage({ type: "TRANSCRIBING", taskId, chunkIndex });
234
- const peak = getPeakAmplitude(audio);
235
- if (peak < 0.012) {
304
+ const { peak, rms } = getAudioStats(audio);
305
+ if (peak < 0.018 || rms < 45e-4) {
236
306
  self.postMessage({
237
307
  type: "RESULT",
238
308
  taskId,
239
309
  chunkIndex,
240
310
  isFinal,
241
311
  silent: true,
312
+ mode,
242
313
  text: ""
243
314
  });
244
315
  return;
245
316
  }
246
- if (peak > 0 && peak < 0.4) {
247
- const gain = Math.min(3, 0.8 / peak);
317
+ if (peak > 0 && peak < 0.35) {
318
+ const gain = Math.min(1.8, 0.45 / peak);
248
319
  for (let i = 0; i < audio.length; i++) {
249
320
  audio[i] = Math.max(-1, Math.min(1, audio[i] * gain));
250
321
  }
251
322
  }
323
+ const durationSec = audio.length / 16e3;
324
+ const windowSec = Math.min(30, Math.max(0.5, durationSec));
325
+ const maxNewTokens = Math.max(24, Math.min(400, Math.round(windowSec * 12) + 16));
252
326
  let streamedText = "";
253
327
  const generateOptions = {
254
328
  language: language || "chinese",
255
- task: task || "transcribe"
329
+ task: task || "transcribe",
330
+ return_timestamps: false,
331
+ do_sample: false,
332
+ temperature: 0,
333
+ repetition_penalty: 1.12,
334
+ no_repeat_ngram_size: 3,
335
+ max_new_tokens: maxNewTokens
256
336
  };
337
+ if (nativeChunking || audio.length > 16e3 * 30) {
338
+ generateOptions.chunk_length_s = 30;
339
+ generateOptions.stride_length_s = 5;
340
+ }
257
341
  try {
258
342
  const tokenizer = asrPipeline.tokenizer;
259
343
  if (tokenizer) {
@@ -261,13 +345,14 @@ async function transcribeAudio(data) {
261
345
  skip_prompt: true,
262
346
  callback_function: (piece) => {
263
347
  if (!piece) return;
348
+ if (typeof taskId === "number" && cancelledTaskIds.has(taskId)) return;
264
349
  streamedText += piece;
265
350
  self.postMessage({
266
351
  type: "PARTIAL",
267
352
  taskId,
268
353
  chunkIndex,
269
354
  delta: piece,
270
- text: streamedText
355
+ text: sanitizeTranscript(streamedText, durationSec)
271
356
  });
272
357
  }
273
358
  });
@@ -276,12 +361,18 @@ async function transcribeAudio(data) {
276
361
  console.warn("[Whisper Worker] 创建文本流失败,回退为整段输出:", streamErr);
277
362
  }
278
363
  const result = await asrPipeline(audio, generateOptions);
279
- const text = (typeof result === "string" ? result : result?.text ?? streamedText ?? "").trim();
364
+ if (typeof taskId === "number" && cancelledTaskIds.has(taskId)) {
365
+ return;
366
+ }
367
+ const raw = (typeof result === "string" ? result : result?.text ?? streamedText ?? "").trim();
368
+ const text = sanitizeTranscript(raw, durationSec);
280
369
  self.postMessage({
281
370
  type: "RESULT",
282
371
  taskId,
283
372
  chunkIndex,
284
373
  isFinal,
374
+ silent: !text,
375
+ mode,
285
376
  text
286
377
  });
287
378
  } catch (err) {
package/dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- .svg-icon-wrapper[data-v-490b11c1]{position:relative;overflow:hidden;vertical-align:middle}.svg-icon[data-v-490b11c1]{width:1em;height:1em;fill:currentColor;vertical-align:middle;display:inline-block}.ai-copy-btn-wrapper{cursor:pointer;width:74px;height:24px;border-radius:12px;box-sizing:border-box;padding:10px 14px;border:1px solid #D9D9D9;display:flex;align-items:center;justify-content:center;font-size:12px;color:#666;line-height:20px;text-align:justify;margin-top:6px}.ai-copy-btn-wrapper .copy-text{margin-left:4px}.markdown-wrapper{line-height:1.2}.markdown-wrapper h1{font-size:2em}.markdown-wrapper h2{font-size:1.5em}.markdown-wrapper h3{font-size:1.25em}.markdown-wrapper h4{font-size:1em}.markdown-wrapper h5{font-size:.875em}.markdown-wrapper h6{font-size:.85em}.markdown-wrapper h1,.markdown-wrapper h2,.markdown-wrapper h3,.markdown-wrapper h4,.markdown-wrapper h5,.markdown-wrapper h6{margin:0 auto;line-height:1.25}.markdown-wrapper ul,.markdown-wrapper ol{padding-left:1.5em;line-height:.8}.markdown-wrapper ul,.markdown-wrapper li,.markdown-wrapper ol{list-style-position:outside;white-space:normal}.markdown-wrapper ul{list-style-type:disc}.markdown-wrapper ol{list-style-type:decimal}.markdown-wrapper li{line-height:1.5}.markdown-wrapper ol ol,.markdown-wrapper ul ul{padding-left:20px}.markdown-wrapper hr{margin:16px 0}.markdown-wrapper a{color:#536fec;font-weight:bolder;text-decoration:underline;padding:0 3px}.markdown-wrapper p{line-height:1.4}.markdown-wrapper p>code{--at-apply: "bg-#e5e5e5";--at-apply: whitespace-pre mx-4px px-6px py-3px rounded-5px}.markdown-wrapper p img{display:inline-block}.markdown-wrapper li>p{line-height:2}.markdown-wrapper strong{font-weight:700}.markdown-wrapper blockquote{padding:10px;margin:20px 0;border-left:5px solid #ccc;background-color:#f9f9f9;color:#555}.markdown-wrapper blockquote>p{margin:0}.ai-panel{margin-right:20px;width:400px;height:804px;background:#fff;border-radius:8px;box-shadow:0 8px 24px #00000026;display:flex;flex-direction:column;overflow:hidden;background-image:url(/images/ai-panel-bg.png);background-size:100% auto;background-position:top;background-repeat:no-repeat;position:relative;transition:all .3s ease}.ai-panel :deep(.el-input-group__append){box-sizing:border-box}.ai-panel.drawer-mode{position:fixed;right:0;top:0;bottom:0;height:100vh;margin:0;border-radius:0;z-index:2000}.ai-panel .panel-header{padding:20px;background:transparent}.ai-panel .panel-header .header-actions{display:flex;justify-content:space-between;gap:12px;align-items:center}.ai-panel .panel-header .header-actions .header-title{font-family:PingFangSC,PingFang SC;font-weight:700;font-size:16px;color:#333;line-height:24px;text-align:left;font-style:normal}.ai-panel .panel-header .header-actions .action-icons{display:flex;gap:12px}.ai-panel .panel-header .header-actions .action-icon{font-size:20px;color:#666;cursor:pointer}.ai-panel .panel-header .header-actions .action-icon:hover{color:#333}.ai-panel .body-content{flex:1;overflow:hidden;padding:20px;display:flex;flex-direction:column}.ai-panel .body-content .welcome-content .title{display:flex;flex-direction:column;align-items:center;margin-bottom:8px}.ai-panel .body-content .welcome-content .title .panel-icon{width:64px;height:64px;margin-bottom:16px}.ai-panel .body-content .welcome-content .title .title-text{margin:0;font-size:24px;color:#333;font-weight:500}.ai-panel .body-content .welcome-content .subtitle{text-align:center;font-size:28px;color:#333;line-height:36px;letter-spacing:2px;margin-bottom:20px}.ai-panel .body-content .welcome-content .subtitle .highlight{margin-left:2px;background:linear-gradient(270deg,#e236ffcc,#0a84ff);-webkit-background-clip:text;color:transparent;font-weight:bolder}.ai-panel .body-content .quick-questions .question-item{padding:12px 16px;background:#f5f7fa;border-radius:8px;margin-bottom:12px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;transition:all .3s}.ai-panel .body-content .quick-questions .question-item:hover{background:#e8f4ff;transform:translate(4px)}.ai-panel .body-content .quick-questions .question-item span{font-size:14px;color:#333}.ai-panel .body-content .quick-questions .question-item .el-icon{color:#666}.ai-panel .body-content .chat-messages{flex:1;overflow-y:auto;overflow-x:hidden;height:100%;display:flex;flex-direction:column}.ai-panel .body-content .chat-messages::-webkit-scrollbar{width:0;background:transparent}.ai-panel .body-content .chat-messages{scrollbar-width:none;-ms-overflow-style:none}.ai-panel .body-content .chat-messages .message-item{display:flex;align-items:flex-start;margin-bottom:20px;gap:12px}.ai-panel .body-content .chat-messages .message-item .message-avatar{width:40px;height:40px;border-radius:20px;flex-shrink:0}.ai-panel .body-content .chat-messages .message-item .user-avatar{background:#0a84ff;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px}.ai-panel .body-content .chat-messages .message-item .message-content{padding:12px 16px;border-radius:2px;max-width:70%;word-break:break-word}.ai-panel .body-content .chat-messages .message-item.ai-message .message-content{background:#f5f7fa}.ai-panel .body-content .chat-messages .message-item.user-message{flex-direction:row-reverse}.ai-panel .body-content .chat-messages .message-item.user-message .message-content{background:#f1f2f3;border-radius:4px 4px 0;color:#333;font-size:14px}.ai-panel .panel-footer{padding:24px;background:#fff;position:relative}.ai-panel .panel-footer .loading-icon{position:absolute;top:-13px}.ai-panel .panel-footer .voice-progress-banner{margin-bottom:12px;padding:10px 14px;background:linear-gradient(135deg,#f0f7ff,#e6f4ff);border:1px solid #bae0ff;border-radius:8px;display:flex;flex-direction:column;gap:6px}.ai-panel .panel-footer .voice-progress-banner .progress-info{display:flex;align-items:center;gap:8px;font-size:13px;color:#0958d9}.ai-panel .panel-footer .voice-progress-banner .progress-info .progress-icon{font-size:14px}.ai-panel .panel-footer .voice-progress-banner .progress-info .progress-text{flex:1;font-weight:500}.ai-panel .panel-footer .voice-progress-banner .progress-info .progress-percent{font-weight:700;font-family:monospace}.ai-panel .panel-footer .voice-progress-banner .progress-track{height:6px;background:#d9d9d9;border-radius:3px;overflow:hidden}.ai-panel .panel-footer .voice-progress-banner .progress-track .progress-bar{height:100%;background:linear-gradient(90deg,#1677ff,#4096ff);border-radius:3px;transition:width .2s ease}.ai-panel .panel-footer .voice-recording-panel{min-height:44px;padding:8px 14px;background:linear-gradient(135deg,#f6ffed,#e6f7ff);border:1px solid #91caff;border-radius:6px;display:flex;flex-direction:column;gap:8px;box-shadow:0 2px 8px #1677ff14}.ai-panel .panel-footer .voice-recording-panel .recording-main{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:28px}.ai-panel .panel-footer .voice-recording-panel .live-transcript{width:100%;max-height:72px;overflow-y:auto;padding:6px 8px;background:#ffffffc7;border-radius:4px;font-size:13px;line-height:1.55;color:#1677ff;word-break:break-all}.ai-panel .panel-footer .voice-recording-panel .live-transcript.empty{color:#8c8c8c}.ai-panel .panel-footer .voice-recording-panel .live-transcript .caret{display:inline-block;margin-left:1px;font-weight:400;color:#1677ff;animation:caret-blink 1s step-end infinite}.ai-panel .panel-footer .voice-recording-panel .recording-status{display:flex;align-items:center;gap:8px}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-pulse{width:10px;height:10px;border-radius:50%;background:#ff4d4f;box-shadow:0 0 #ff4d4f66;animation:pulse 1.5s infinite}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-pulse.transcribing{background:#1890ff;box-shadow:0 0 #1890ff66}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-time{font-family:monospace;font-weight:700;font-size:13px;color:#ff4d4f}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-hint{font-size:13px;color:#333}.ai-panel .panel-footer .voice-recording-panel .recording-status .volume-waves{display:flex;align-items:center;gap:3px;height:30px;margin-left:4px}.ai-panel .panel-footer .voice-recording-panel .recording-status .volume-waves .wave{width:3px;background:#1890ff;border-radius:2px;transition:height .08s ease}.ai-panel .panel-footer .voice-recording-panel .recording-actions{display:flex;align-items:center;gap:8px}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-btn{color:#8c8c8c;border-color:#d9d9d9}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-btn:hover{color:#ff4d4f;border-color:#ff4d4f;background:#fff1f0}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-finish-btn{background:#1677ff;border-color:#1677ff;padding:6px 14px;font-weight:500}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-transcribe-btn{color:#666;border-color:#d9d9d9;background:#fff;font-size:12px;padding:4px 10px;height:28px;transition:all .2s}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-transcribe-btn:hover{color:#ff4d4f;border-color:#ff4d4f;background:#fff1f0}.ai-panel .panel-footer .voice-playback-bar{margin-bottom:8px;height:36px;padding:0 12px;background:#f0f7ff;border:1px solid #bae0ff;border-radius:6px;display:flex;align-items:center;justify-content:space-between;transition:all .2s ease}.ai-panel .panel-footer .voice-playback-bar .playback-main{display:flex;align-items:center;gap:8px;cursor:pointer;-webkit-user-select:none;user-select:none}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-play-icon{width:22px;height:22px;border-radius:50%;background:#1677ff;color:#fff;display:flex;align-items:center;justify-content:center;transition:transform .15s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-play-icon:hover{transform:scale(1.1)}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-title{font-size:13px;color:#1677ff;font-weight:500}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-time{font-size:12px;color:#8c8c8c;font-family:monospace}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves{display:flex;align-items:flex-end;gap:2px;height:14px;margin-left:4px}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar{width:2px;background:#1677ff;border-radius:1px;animation:soundWave .8s ease-in-out infinite alternate}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(1){height:6px;animation-delay:0s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(2){height:12px;animation-delay:.2s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(3){height:8px;animation-delay:.4s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(4){height:14px;animation-delay:.1s}.ai-panel .panel-footer .voice-playback-bar .playback-close{cursor:pointer;color:#8c8c8c;padding:4px;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:all .2s}.ai-panel .panel-footer .voice-playback-bar .playback-close:hover{color:#ff4d4f;background:#fff1f0}.ai-panel .panel-footer .input-box .el-input-group{height:40px;border-radius:4px}.ai-panel .panel-footer .input-box :deep(.el-input__wrapper){box-shadow:none}.ai-panel .panel-footer .input-box :deep(.el-input-group__append){box-shadow:none;background:transparent;padding:8px 12px}.ai-panel .panel-footer .input-box .input-actions-box{display:flex;align-items:center;gap:12px}.ai-panel .panel-footer .input-box .input-actions-box .voice-upload-btn{display:flex;align-items:center;justify-content:center;cursor:pointer;color:#666;transition:all .2s;padding:4px;border-radius:4px}.ai-panel .panel-footer .input-box .input-actions-box .voice-upload-btn:hover{color:#1677ff;background:#f0f7ff;transform:scale(1.08)}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn{display:flex;align-items:center;justify-content:center;cursor:pointer;color:#666;transition:all .2s;padding:4px;border-radius:4px}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn:hover{color:#1677ff;background:#f0f7ff;transform:scale(1.08)}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn.loading-anim{color:#1677ff}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn.loading-anim svg{animation:mic-breathe 1.2s ease-in-out infinite;transform-origin:center}.ai-panel .panel-footer .input-box .input-actions-box .send-icon-box{display:flex;align-items:center;justify-content:center;cursor:pointer}.ai-panel .panel-footer .input-box .el-input-group__append{background-color:transparent}@keyframes soundWave{0%{height:3px}to{height:14px}}@keyframes pulse{0%{box-shadow:0 0 #ff4d4fb3}70%{box-shadow:0 0 0 8px #ff4d4f00}to{box-shadow:0 0 #ff4d4f00}}@keyframes caret-blink{0%,to{opacity:1}50%{opacity:0}}@keyframes mic-breathe{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.22);opacity:.72}}/*!
1
+ @charset "UTF-8";.svg-icon-wrapper[data-v-490b11c1]{position:relative;overflow:hidden;vertical-align:middle}.svg-icon[data-v-490b11c1]{width:1em;height:1em;fill:currentColor;vertical-align:middle;display:inline-block}.ai-copy-btn-wrapper{cursor:pointer;width:74px;height:24px;border-radius:12px;box-sizing:border-box;padding:10px 14px;border:1px solid #D9D9D9;display:flex;align-items:center;justify-content:center;font-size:12px;color:#666;line-height:20px;text-align:justify;margin-top:6px}.ai-copy-btn-wrapper .copy-text{margin-left:4px}.ai-thinking-block{margin-bottom:10px;border:1px solid #E8E8E8;border-radius:6px;background:#fafafa;overflow:hidden}.ai-thinking-block .thinking-header{display:flex;align-items:center;gap:6px;padding:7px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:12px;color:#666;transition:background-color .2s ease}.ai-thinking-block .thinking-header:hover{background-color:#f0f7ff;color:#1677ff}.ai-thinking-block .thinking-header:hover .thinking-toggle-hint{color:#1677ff}.ai-thinking-block .thinking-header .thinking-arrow{flex-shrink:0;transition:transform .2s ease}.ai-thinking-block .thinking-header .thinking-title{flex:1;text-align:left;font-weight:500;line-height:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ai-thinking-block .thinking-header .thinking-toggle-hint{flex-shrink:0;color:#999}.ai-thinking-block.is-expanded .thinking-arrow{transform:rotate(90deg)}.ai-thinking-block.is-streaming{border-color:#bae0ff;background:linear-gradient(135deg,#f0f7ff,#e6f4ff)}.ai-thinking-block.is-streaming .thinking-header .thinking-title{color:#1677ff;animation:thinking-breathe 1.2s ease-in-out infinite}.ai-thinking-block .thinking-body{max-height:280px;overflow-y:auto;padding:8px 12px 10px;border-top:1px dashed #E8E8E8;font-size:13px;color:#8c8c8c;line-height:1.6;word-break:break-word}.ai-thinking-block .thinking-body p{margin:0 0 4px}.ai-thinking-block .thinking-body p:last-child{margin-bottom:0}@keyframes thinking-breathe{0%,to{opacity:1}50%{opacity:.55}}.markdown-wrapper{font-size:14px;line-height:1.75;color:#333;word-break:break-word}.markdown-wrapper p{margin:0 0 10px}.markdown-wrapper p:last-child{margin-bottom:0}.markdown-wrapper h1,.markdown-wrapper h2,.markdown-wrapper h3,.markdown-wrapper h4,.markdown-wrapper h5,.markdown-wrapper h6{margin:14px 0 10px;font-weight:600;line-height:1.4}.markdown-wrapper h1:first-child,.markdown-wrapper h2:first-child,.markdown-wrapper h3:first-child,.markdown-wrapper h4:first-child,.markdown-wrapper h5:first-child,.markdown-wrapper h6:first-child{margin-top:0}.markdown-wrapper h1{font-size:18px}.markdown-wrapper h2{font-size:17px}.markdown-wrapper h3{font-size:16px}.markdown-wrapper h4,.markdown-wrapper h5,.markdown-wrapper h6{font-size:15px}.markdown-wrapper ul,.markdown-wrapper ol{margin:0 0 10px;padding-left:1.5em}.markdown-wrapper ul:last-child,.markdown-wrapper ol:last-child{margin-bottom:0}.markdown-wrapper li{margin:4px 0;line-height:1.7}.markdown-wrapper li>p{margin:0;line-height:1.7}.markdown-wrapper hr{margin:14px 0;border:none;border-top:1px solid #e8e8e8}.markdown-wrapper a{color:#536fec;font-weight:bolder;text-decoration:underline;padding:0 3px}.markdown-wrapper strong{font-weight:600}.markdown-wrapper code{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace}.markdown-wrapper p>code,.markdown-wrapper li>code,.markdown-wrapper td>code{background:#536fec14;color:#4761c6;padding:2px 6px;border-radius:4px;font-size:12.5px;white-space:pre-wrap}.markdown-wrapper pre.md-code-block{margin:0 0 10px;padding:12px 14px;background:#f6f8fa;border:1px solid #e8ecf2;border-radius:8px;overflow:auto;max-height:380px;font-size:12.5px;line-height:1.6}.markdown-wrapper pre.md-code-block:last-child{margin-bottom:0}.markdown-wrapper pre.md-code-block code{display:block;padding:0;background:transparent;color:#333;white-space:pre;font-size:inherit;line-height:inherit}.markdown-wrapper blockquote{padding:10px 14px;margin:10px 0;border-left:4px solid #c9d4f0;background-color:#f7f9fd;border-radius:0 6px 6px 0;color:#555}.markdown-wrapper blockquote>p{margin:0}.markdown-wrapper table{width:100%;margin:10px 0;border-collapse:collapse;font-size:13px}.markdown-wrapper table th,.markdown-wrapper table td{border:1px solid #e0e6ef;padding:6px 10px;text-align:left}.markdown-wrapper table th{background:#f2f5fa;font-weight:600}.markdown-wrapper table tr:nth-child(2n) td{background:#fafbfd}.markdown-wrapper img{display:inline-block;max-width:100%}/*!
2
2
  Theme: Default
3
3
  Description: Original highlight.js style
4
4
  Author: (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
@@ -6,4 +6,4 @@
6
6
  Website: https://highlightjs.org/
7
7
  License: see project LICENSE
8
8
  Touched: 2021
9
- */pre code.hljs[data-v-0c5630f1]{display:block;overflow-x:auto;padding:1em}code.hljs[data-v-0c5630f1]{padding:3px 5px}.hljs[data-v-0c5630f1]{background:#f3f3f3;color:#444}.hljs-comment[data-v-0c5630f1]{color:#697070}.hljs-punctuation[data-v-0c5630f1],.hljs-tag[data-v-0c5630f1]{color:#444a}.hljs-tag .hljs-attr[data-v-0c5630f1],.hljs-tag .hljs-name[data-v-0c5630f1]{color:#444}.hljs-attribute[data-v-0c5630f1],.hljs-doctag[data-v-0c5630f1],.hljs-keyword[data-v-0c5630f1],.hljs-meta .hljs-keyword[data-v-0c5630f1],.hljs-name[data-v-0c5630f1],.hljs-selector-tag[data-v-0c5630f1]{font-weight:700}.hljs-deletion[data-v-0c5630f1],.hljs-number[data-v-0c5630f1],.hljs-quote[data-v-0c5630f1],.hljs-selector-class[data-v-0c5630f1],.hljs-selector-id[data-v-0c5630f1],.hljs-string[data-v-0c5630f1],.hljs-template-tag[data-v-0c5630f1],.hljs-type[data-v-0c5630f1]{color:#800}.hljs-section[data-v-0c5630f1],.hljs-title[data-v-0c5630f1]{color:#800;font-weight:700}.hljs-link[data-v-0c5630f1],.hljs-operator[data-v-0c5630f1],.hljs-regexp[data-v-0c5630f1],.hljs-selector-attr[data-v-0c5630f1],.hljs-selector-pseudo[data-v-0c5630f1],.hljs-symbol[data-v-0c5630f1],.hljs-template-variable[data-v-0c5630f1],.hljs-variable[data-v-0c5630f1]{color:#ab5656}.hljs-literal[data-v-0c5630f1]{color:#695}.hljs-addition[data-v-0c5630f1],.hljs-built_in[data-v-0c5630f1],.hljs-bullet[data-v-0c5630f1],.hljs-code[data-v-0c5630f1]{color:#397300}.hljs-meta[data-v-0c5630f1]{color:#1f7199}.hljs-meta .hljs-string[data-v-0c5630f1]{color:#38a}.hljs-emphasis[data-v-0c5630f1]{font-style:italic}.hljs-strong[data-v-0c5630f1]{font-weight:700}.ai-assistant{box-sizing:border-box;position:fixed;right:20px;bottom:40px;z-index:1000;display:flex;align-items:flex-end}.ai-assistant div{box-sizing:border-box}.ai-assistant .ai-icon{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;cursor:pointer;width:44px;padding:6px;transition:all .3s;height:114px;background-color:#fff;box-shadow:0 4px 16px 4px #00000008,0 2px 8px #0000000d,0 0 4px -2px #00000014;border-radius:22px;border:1px solid transparent;background-image:linear-gradient(#fff,#fff),linear-gradient(180deg,#60fffc,#0a84ff);background-origin:border-box;background-clip:padding-box,border-box}.ai-assistant .ai-icon:hover{transform:translateY(-2px);box-shadow:0 4px 16px #00000026}.ai-assistant .ai-icon img{width:32px;height:32px;margin-bottom:6px}.ai-assistant .ai-icon .ai-icon-text{display:inline-block;width:20px;font-size:16px;line-height:18px;font-weight:700;color:#333}.ai-assistant .ai-icon:hover .close-icon{display:flex}.ai-assistant .ai-icon .close-icon{display:none;position:absolute;top:-6px;right:-6px;width:16px;height:16px;background:#fff;border-radius:50%;align-items:center;justify-content:center;box-shadow:0 2px 4px #0000001a;color:#666;cursor:pointer;z-index:1}.ai-assistant .ai-icon .close-icon:hover{color:#333;background:#f5f5f5}
9
+ */pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.slide-enter-active,.slide-leave-active{transition:transform .3s ease}.slide-enter-from,.slide-leave-to{transform:translate(30px)}.ai-panel{margin-right:20px;width:400px;height:804px;background:#fff;border-radius:8px;box-shadow:0 8px 24px #00000026;display:flex;flex-direction:column;overflow:hidden;background-image:url(/images/ai-panel-bg.png);background-size:100% auto;background-position:top;background-repeat:no-repeat;position:relative;transition:all .3s ease}.ai-panel :deep(.el-input-group__append){box-sizing:border-box}.ai-panel.drawer-mode{position:fixed;right:0;top:0;bottom:0;height:100vh;margin:0;border-radius:0;z-index:2000}.ai-panel.embedded-mode{width:100%;height:100%;margin:0;box-shadow:none;border-radius:0}.ai-panel .panel-header{padding:20px;background:transparent}.ai-panel .panel-header .header-actions{display:flex;justify-content:space-between;gap:12px;align-items:center}.ai-panel .panel-header .header-actions .header-title{font-family:PingFangSC,PingFang SC;font-weight:700;font-size:16px;color:#333;line-height:24px;text-align:left;font-style:normal}.ai-panel .panel-header .header-actions .action-icons{display:flex;gap:12px}.ai-panel .panel-header .header-actions .action-icon{font-size:20px;color:#666;cursor:pointer}.ai-panel .panel-header .header-actions .action-icon:hover{color:#333}.ai-panel .body-content{flex:1;overflow:hidden;padding:20px;display:flex;flex-direction:column}.ai-panel .body-content .welcome-content .title{display:flex;flex-direction:column;align-items:center;margin-bottom:8px}.ai-panel .body-content .welcome-content .title .panel-icon{width:64px;height:64px;margin-bottom:16px}.ai-panel .body-content .welcome-content .title .title-text{margin:0;font-size:24px;color:#333;font-weight:500}.ai-panel .body-content .welcome-content .subtitle{text-align:center;font-size:28px;color:#333;line-height:36px;letter-spacing:2px;margin-bottom:20px}.ai-panel .body-content .welcome-content .subtitle .highlight{margin-left:2px;background:linear-gradient(270deg,#e236ffcc,#0a84ff);-webkit-background-clip:text;color:transparent;font-weight:bolder}.ai-panel .body-content .quick-questions .question-item{padding:12px 16px;background:#f5f7fa;border-radius:8px;margin-bottom:12px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;transition:all .3s}.ai-panel .body-content .quick-questions .question-item:hover{background:#e8f4ff;transform:translate(4px)}.ai-panel .body-content .quick-questions .question-item span{font-size:14px;color:#333}.ai-panel .body-content .quick-questions .question-item .el-icon{color:#666}.ai-panel .body-content .chat-messages{flex:1;overflow-y:auto;overflow-x:hidden;height:100%;display:flex;flex-direction:column}.ai-panel .body-content .chat-messages::-webkit-scrollbar{width:0;background:transparent}.ai-panel .body-content .chat-messages{scrollbar-width:none;-ms-overflow-style:none}.ai-panel .body-content .chat-messages .message-item{display:flex;align-items:flex-start;margin-bottom:20px;gap:12px}.ai-panel .body-content .chat-messages .message-item .message-avatar{width:40px;height:40px;border-radius:20px;flex-shrink:0}.ai-panel .body-content .chat-messages .message-item .user-avatar{background:#0a84ff;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px}.ai-panel .body-content .chat-messages .message-item .message-content{padding:12px 16px;border-radius:2px;max-width:70%;word-break:break-word}.ai-panel .body-content .chat-messages .message-item.ai-message .message-content{background:#f5f7fa;font-size:14px}.ai-panel .body-content .chat-messages .message-item.user-message{flex-direction:row-reverse}.ai-panel .body-content .chat-messages .message-item.user-message .message-content{background:#f1f2f3;border-radius:4px 4px 0;color:#333;font-size:14px}.ai-panel .panel-footer{padding:24px;background:#fff;position:relative}.ai-panel .panel-footer .loading-icon{position:absolute;top:-13px}.ai-panel .panel-footer .voice-progress-banner{margin-bottom:12px;padding:10px 14px;background:linear-gradient(135deg,#f0f7ff,#e6f4ff);border:1px solid #bae0ff;border-radius:8px;display:flex;flex-direction:column;gap:6px}.ai-panel .panel-footer .voice-progress-banner .progress-info{display:flex;align-items:center;gap:8px;font-size:13px;color:#0958d9}.ai-panel .panel-footer .voice-progress-banner .progress-info .progress-icon{font-size:14px}.ai-panel .panel-footer .voice-progress-banner .progress-info .progress-text{flex:1;font-weight:500}.ai-panel .panel-footer .voice-progress-banner .progress-info .progress-percent{font-weight:700;font-family:monospace}.ai-panel .panel-footer .voice-progress-banner .progress-track{height:6px;background:#d9d9d9;border-radius:3px;overflow:hidden}.ai-panel .panel-footer .voice-progress-banner .progress-track .progress-bar{height:100%;background:linear-gradient(90deg,#1677ff,#4096ff);border-radius:3px;transition:width .2s ease}.ai-panel .panel-footer .voice-recording-panel{min-height:44px;padding:8px 14px;background:linear-gradient(135deg,#f6ffed,#e6f7ff);border:1px solid #91caff;border-radius:6px;display:flex;flex-direction:column;gap:8px;box-shadow:0 2px 8px #1677ff14}.ai-panel .panel-footer .voice-recording-panel .recording-main{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:28px}.ai-panel .panel-footer .voice-recording-panel .live-transcript{width:100%;max-height:72px;overflow-y:auto;padding:6px 8px;background:#ffffffc7;border-radius:4px;font-size:13px;line-height:1.55;color:#1677ff;word-break:break-all}.ai-panel .panel-footer .voice-recording-panel .live-transcript.empty{color:#8c8c8c}.ai-panel .panel-footer .voice-recording-panel .live-transcript .caret{display:inline-block;margin-left:1px;font-weight:400;color:#1677ff;animation:caret-blink 1s step-end infinite}.ai-panel .panel-footer .voice-recording-panel .recording-status{display:flex;align-items:center;gap:8px}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-pulse{width:10px;height:10px;border-radius:50%;background:#ff4d4f;box-shadow:0 0 #ff4d4f66;animation:pulse 1.5s infinite}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-pulse.transcribing{background:#1890ff;box-shadow:0 0 #1890ff66}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-time{font-family:monospace;font-weight:700;font-size:13px;color:#ff4d4f}.ai-panel .panel-footer .voice-recording-panel .recording-status .recording-hint{font-size:13px;color:#333}.ai-panel .panel-footer .voice-recording-panel .recording-status .volume-waves{display:flex;align-items:center;gap:3px;height:30px;margin-left:4px}.ai-panel .panel-footer .voice-recording-panel .recording-status .volume-waves .wave{width:3px;background:#1890ff;border-radius:2px;transition:height .08s ease}.ai-panel .panel-footer .voice-recording-panel .recording-actions{display:flex;align-items:center;gap:8px}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-btn{color:#8c8c8c;border-color:#d9d9d9}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-btn:hover{color:#ff4d4f;border-color:#ff4d4f;background:#fff1f0}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-finish-btn{background:#1677ff;border-color:#1677ff;padding:6px 14px;font-weight:500}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-transcribe-btn{color:#666;border-color:#d9d9d9;background:#fff;font-size:12px;padding:4px 10px;height:28px;transition:all .2s}.ai-panel .panel-footer .voice-recording-panel .recording-actions .voice-cancel-transcribe-btn:hover{color:#ff4d4f;border-color:#ff4d4f;background:#fff1f0}.ai-panel .panel-footer .voice-playback-bar{margin-bottom:8px;height:36px;padding:0 12px;background:#f0f7ff;border:1px solid #bae0ff;border-radius:6px;display:flex;align-items:center;justify-content:space-between;transition:all .2s ease}.ai-panel .panel-footer .voice-playback-bar .playback-main{display:flex;align-items:center;gap:8px;cursor:pointer;-webkit-user-select:none;user-select:none}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-play-icon{width:22px;height:22px;border-radius:50%;background:#1677ff;color:#fff;display:flex;align-items:center;justify-content:center;transition:transform .15s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-play-icon:hover{transform:scale(1.1)}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-title{font-size:13px;color:#1677ff;font-weight:500}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-time{font-size:12px;color:#8c8c8c;font-family:monospace}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves{display:flex;align-items:flex-end;gap:2px;height:14px;margin-left:4px}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar{width:2px;background:#1677ff;border-radius:1px;animation:soundWave .8s ease-in-out infinite alternate}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(1){height:6px;animation-delay:0s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(2){height:12px;animation-delay:.2s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(3){height:8px;animation-delay:.4s}.ai-panel .panel-footer .voice-playback-bar .playback-main .playback-waves .wave-bar:nth-child(4){height:14px;animation-delay:.1s}.ai-panel .panel-footer .voice-playback-bar .playback-close{cursor:pointer;color:#8c8c8c;padding:4px;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:all .2s}.ai-panel .panel-footer .voice-playback-bar .playback-close:hover{color:#ff4d4f;background:#fff1f0}.ai-panel .panel-footer .input-box .el-input-group{height:40px;border-radius:4px}.ai-panel .panel-footer .input-box :deep(.el-input__wrapper){box-shadow:none}.ai-panel .panel-footer .input-box :deep(.el-input-group__append){box-shadow:none;background:transparent;padding:8px 12px}.ai-panel .panel-footer .input-box .input-actions-box{display:flex;align-items:center;gap:12px}.ai-panel .panel-footer .input-box .input-actions-box .voice-upload-btn{display:flex;align-items:center;justify-content:center;cursor:pointer;color:#666;transition:all .2s;padding:4px;border-radius:4px}.ai-panel .panel-footer .input-box .input-actions-box .voice-upload-btn:hover{color:#1677ff;background:#f0f7ff;transform:scale(1.08)}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn{display:flex;align-items:center;justify-content:center;cursor:pointer;color:#666;transition:all .2s;padding:4px;border-radius:4px}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn:hover{color:#1677ff;background:#f0f7ff;transform:scale(1.08)}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn.loading-anim{color:#1677ff}.ai-panel .panel-footer .input-box .input-actions-box .voice-mic-btn.loading-anim svg{animation:mic-breathe 1.2s ease-in-out infinite;transform-origin:center}.ai-panel .panel-footer .input-box .input-actions-box .send-icon-box{display:flex;align-items:center;justify-content:center;cursor:pointer}.ai-panel .panel-footer .input-box .el-input-group__append{background-color:transparent}@keyframes soundWave{0%{height:3px}to{height:14px}}@keyframes pulse{0%{box-shadow:0 0 #ff4d4fb3}70%{box-shadow:0 0 0 8px #ff4d4f00}to{box-shadow:0 0 #ff4d4f00}}@keyframes caret-blink{0%,to{opacity:1}50%{opacity:0}}@keyframes mic-breathe{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.22);opacity:.72}}.ai-assistant{box-sizing:border-box;position:fixed;right:20px;bottom:40px;z-index:1000;display:flex;align-items:flex-end}.ai-assistant div{box-sizing:border-box}.ai-assistant .ai-icon{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;cursor:pointer;width:44px;padding:6px;transition:all .3s;height:114px;background-color:#fff;box-shadow:0 4px 16px 4px #00000008,0 2px 8px #0000000d,0 0 4px -2px #00000014;border-radius:22px;border:1px solid transparent;background-image:linear-gradient(#fff,#fff),linear-gradient(180deg,#60fffc,#0a84ff);background-origin:border-box;background-clip:padding-box,border-box}.ai-assistant .ai-icon:hover{transform:translateY(-2px);box-shadow:0 4px 16px #00000026}.ai-assistant .ai-icon img{width:32px;height:32px;margin-bottom:6px}.ai-assistant .ai-icon .ai-icon-text{display:inline-block;width:20px;font-size:16px;line-height:18px;font-weight:700;color:#333}.ai-assistant .ai-icon:hover .close-icon{display:flex}.ai-assistant .ai-icon .close-icon{display:none;position:absolute;top:-6px;right:-6px;width:16px;height:16px;background:#fff;border-radius:50%;align-items:center;justify-content:center;box-shadow:0 2px 4px #0000001a;color:#666;cursor:pointer;z-index:1}.ai-assistant .ai-icon .close-icon:hover{color:#333;background:#f5f5f5}.ai-chat-plain{box-sizing:border-box;position:relative;width:100%;height:100%}.ai-chat-plain div{box-sizing:border-box}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@szjy/ai-coms",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "vue3 ai component",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.mjs",
@@ -1,8 +0,0 @@
1
- /**
2
- * Whisper 中文转写默认偏台湾繁体,出字前转为大陆简体。
3
- * 先替换常见词组,再按单字对照表转换。
4
- */
5
- /**
6
- * 将繁体中文转为简体中文。非中文内容原样返回。
7
- */
8
- export declare function toSimplifiedChinese(input: string): string;