@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.
- package/README.md +3 -1
- package/dist/index.mjs +1316 -3410
- package/dist/index.umd.js +2 -2
- package/dist/packages/api/ai.d.ts +12 -7
- package/dist/packages/common/audio/recorder.d.ts +13 -4
- package/dist/packages/common/audio/transcript-sanitize.d.ts +16 -0
- package/dist/packages/common/audio/voice-manager.d.ts +5 -15
- package/dist/packages/components/AiChat/src/components/plugins/markdown.d.ts +2 -2
- package/dist/packages/components/AiChat/src/composables/useChatDeps.d.ts +6 -0
- package/dist/packages/components/AiChat/src/index.vue.d.ts +31 -1
- package/dist/packages/components/AiChat/src/transform/index.d.ts +12 -0
- package/dist/packages/components/AiChatPlain/index.d.ts +3 -0
- package/dist/packages/components/AiChatPlain/src/index.vue.d.ts +162 -0
- package/dist/packages/components/components.d.ts +1 -0
- package/dist/scripts/ai/README.md +8 -1
- package/dist/scripts/ai/whisper.worker.js +104 -13
- package/dist/style.css +2 -2
- package/package.json +1 -1
- package/dist/packages/common/audio/zh-simplified.d.ts +0 -8
|
@@ -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
|
|
100
|
-
private emitLiveText;
|
|
91
|
+
private emitPartial;
|
|
101
92
|
private finishStream;
|
|
102
93
|
/**
|
|
103
|
-
*
|
|
104
|
-
* isFinal=true 表示采集已结束,发完剩余尾巴后收口。
|
|
94
|
+
* 录音结束或上传:整段一次送入 Worker。超过 30s 由 Worker 按重叠窗口切分。
|
|
105
95
|
*/
|
|
106
|
-
private
|
|
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 };
|
|
@@ -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,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;
|
|
@@ -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
|
|
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
|
|
208
|
-
let
|
|
269
|
+
function getAudioStats(audio) {
|
|
270
|
+
let peak = 0;
|
|
271
|
+
let sumSq = 0;
|
|
209
272
|
for (let i = 0; i < audio.length; i++) {
|
|
210
|
-
const
|
|
211
|
-
|
|
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
|
|
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 =
|
|
235
|
-
if (peak < 0.
|
|
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.
|
|
247
|
-
const gain = Math.min(
|
|
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
|
-
|
|
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