@szjy/ai-coms 0.1.8 → 0.1.10
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 +8 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +3929 -658
- package/dist/index.umd.js +2 -2
- package/dist/packages/common/audio/opfs-cache.d.ts +30 -0
- package/dist/packages/common/audio/recorder.d.ts +52 -0
- package/dist/packages/common/audio/transformers-runtime.d.ts +6 -0
- package/dist/packages/common/audio/voice-manager.d.ts +109 -0
- package/dist/packages/common/audio/whisper.worker.d.ts +7 -0
- package/dist/packages/common/audio/zh-simplified.d.ts +8 -0
- package/dist/packages/components/AiChat/src/index.vue.d.ts +30 -0
- package/dist/scripts/ai/README.md +14 -0
- package/dist/scripts/ai/whisper.worker.js +297 -0
- package/dist/style.css +2 -2
- package/package.json +19 -6
- package/dist/vite.svg +0 -1
|
@@ -42,6 +42,20 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
|
|
|
42
42
|
type: ObjectConstructor;
|
|
43
43
|
default: () => {};
|
|
44
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
|
+
};
|
|
45
59
|
}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
46
60
|
token: {
|
|
47
61
|
type: StringConstructor;
|
|
@@ -86,6 +100,20 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
|
|
|
86
100
|
type: ObjectConstructor;
|
|
87
101
|
default: () => {};
|
|
88
102
|
};
|
|
103
|
+
/**
|
|
104
|
+
* 语音识别模型静态资源基础路径,默认为 '/sounds/'
|
|
105
|
+
*/
|
|
106
|
+
soundBaseUrl: {
|
|
107
|
+
type: StringConstructor;
|
|
108
|
+
default: string;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Whisper Worker 脚本地址。不传则自动探测库产物与 /scripts/ai/whisper.worker.js
|
|
112
|
+
*/
|
|
113
|
+
workerUrl: {
|
|
114
|
+
type: StringConstructor;
|
|
115
|
+
default: string;
|
|
116
|
+
};
|
|
89
117
|
}>> & Readonly<{}>, {
|
|
90
118
|
token: string;
|
|
91
119
|
identifier: string;
|
|
@@ -94,5 +122,7 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
|
|
|
94
122
|
llmName: string;
|
|
95
123
|
messagePostRender: Function;
|
|
96
124
|
extraConfig: Record<string, any>;
|
|
125
|
+
soundBaseUrl: string;
|
|
126
|
+
workerUrl: string;
|
|
97
127
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
98
128
|
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 语音静态脚本
|
|
2
|
+
|
|
3
|
+
`pnpm build:voice` 会生成:
|
|
4
|
+
|
|
5
|
+
| 文件 | 大约体积 | 是否进 git | 何时更新 |
|
|
6
|
+
| :--- | ---: | :--- | :--- |
|
|
7
|
+
| `whisper.worker.js` | ~10 KB | 可以 | 改 `whisper.worker.ts` 协议时 |
|
|
8
|
+
| `transformers.runtime.js` | ~56 MB | 否 | 升级 `@huggingface/transformers` |
|
|
9
|
+
|
|
10
|
+
日常改识别协议只提交 / 重拷 `whisper.worker.js`。大运行时请加入宿主 `.gitignore`:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
public/scripts/ai/transformers.runtime.js
|
|
14
|
+
```
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { env, pipeline, WhisperTextStreamer } from "./transformers.runtime.js";
|
|
2
|
+
const DEFAULT_CACHE_DIR = "szjy-voice-models";
|
|
3
|
+
const FALLBACK_CACHE_NAME = "szjy-voice-cache-v1";
|
|
4
|
+
function isOPFSSupported() {
|
|
5
|
+
return typeof navigator !== "undefined" && !!navigator.storage && typeof navigator.storage.getDirectory === "function";
|
|
6
|
+
}
|
|
7
|
+
async function clearVoiceModelCache(dirName = DEFAULT_CACHE_DIR) {
|
|
8
|
+
let cleared = false;
|
|
9
|
+
if (isOPFSSupported()) {
|
|
10
|
+
try {
|
|
11
|
+
const root = await navigator.storage.getDirectory();
|
|
12
|
+
await root.removeEntry(dirName, { recursive: true });
|
|
13
|
+
cleared = true;
|
|
14
|
+
console.log(`[OPFS] 成功清空语音模型缓存目录: ${dirName}`);
|
|
15
|
+
} catch (err) {
|
|
16
|
+
if (err.name === "NotFoundError") {
|
|
17
|
+
cleared = true;
|
|
18
|
+
} else {
|
|
19
|
+
console.warn(`[OPFS] 清理目录 ${dirName} 异常:`, err);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (typeof caches !== "undefined") {
|
|
24
|
+
try {
|
|
25
|
+
const cacheKeys = await caches.keys();
|
|
26
|
+
for (const key of cacheKeys) {
|
|
27
|
+
if (key.includes("transformers") || key.includes("szjy-voice") || key === FALLBACK_CACHE_NAME) {
|
|
28
|
+
await caches.delete(key);
|
|
29
|
+
cleared = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.warn("[CacheStorage] 清除缓存异常:", err);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return cleared;
|
|
37
|
+
}
|
|
38
|
+
if (env?.backends?.onnx?.wasm) {
|
|
39
|
+
env.backends.onnx.wasm.wasmPaths = new URL(
|
|
40
|
+
/* @vite-ignore */
|
|
41
|
+
"./",
|
|
42
|
+
import.meta.url
|
|
43
|
+
).href;
|
|
44
|
+
}
|
|
45
|
+
let asrPipeline = null;
|
|
46
|
+
let isInitializing = false;
|
|
47
|
+
let transcribeQueue = [];
|
|
48
|
+
let transcribeRunning = false;
|
|
49
|
+
const originalFetch = self.fetch.bind(self);
|
|
50
|
+
self.fetch = async (input, init) => {
|
|
51
|
+
const response = await originalFetch(input, init);
|
|
52
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input?.url || "";
|
|
53
|
+
const contentType = response.headers.get("content-type") || "";
|
|
54
|
+
if (response.ok && (contentType.includes("text/html") || contentType.includes("application/xhtml+xml")) && (url.includes("/sounds/") || url.endsWith(".json") || url.endsWith(".onnx") || url.endsWith(".txt") || url.endsWith(".wasm"))) {
|
|
55
|
+
return new Response("File not found", {
|
|
56
|
+
status: 404,
|
|
57
|
+
statusText: "Not Found",
|
|
58
|
+
headers: { "Content-Type": "text/plain" }
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return response;
|
|
62
|
+
};
|
|
63
|
+
env.allowLocalModels = true;
|
|
64
|
+
env.useBrowserCache = typeof caches !== "undefined";
|
|
65
|
+
self.addEventListener("message", async (e) => {
|
|
66
|
+
const { type, data } = e.data;
|
|
67
|
+
switch (type) {
|
|
68
|
+
case "INIT":
|
|
69
|
+
await initPipeline(data);
|
|
70
|
+
break;
|
|
71
|
+
case "TRANSCRIBE":
|
|
72
|
+
await enqueueTranscribe(data);
|
|
73
|
+
break;
|
|
74
|
+
case "CLEAR_CACHE":
|
|
75
|
+
try {
|
|
76
|
+
await clearVoiceModelCache();
|
|
77
|
+
asrPipeline = null;
|
|
78
|
+
self.postMessage({ type: "CACHE_CLEARED" });
|
|
79
|
+
} catch (err) {
|
|
80
|
+
self.postMessage({ type: "ERROR", error: err.message || "清理缓存失败" });
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
console.warn("[Whisper Worker] 未知指令:", type);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
async function sanitizeTransformersCache() {
|
|
88
|
+
if (typeof caches === "undefined") return;
|
|
89
|
+
try {
|
|
90
|
+
const cache = await caches.open("transformers-cache");
|
|
91
|
+
const requests = await cache.keys();
|
|
92
|
+
for (const req of requests) {
|
|
93
|
+
const resp = await cache.match(req);
|
|
94
|
+
if (resp) {
|
|
95
|
+
const ct = resp.headers.get("content-type") || "";
|
|
96
|
+
if (ct.includes("text/html") || ct.includes("application/xhtml+xml")) {
|
|
97
|
+
await cache.delete(req);
|
|
98
|
+
console.warn("[Whisper Worker] 清理了已污染的 HTML 缓存项:", req.url);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const clone = resp.clone();
|
|
103
|
+
const text = await clone.text();
|
|
104
|
+
if (text.trim().startsWith("<")) {
|
|
105
|
+
await cache.delete(req);
|
|
106
|
+
console.warn("[Whisper Worker] 清理了已污染的 HTML 文本缓存项:", req.url);
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} catch (e) {
|
|
113
|
+
console.warn("[Whisper Worker] 检查缓存异常:", e);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function checkLocalModelExists(baseUrl, modelId) {
|
|
117
|
+
try {
|
|
118
|
+
const normalized = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
119
|
+
const testUrl = `${normalized}${modelId}/config.json`;
|
|
120
|
+
const res = await fetch(testUrl, { method: "GET" });
|
|
121
|
+
const contentType = res.headers.get("content-type") || "";
|
|
122
|
+
if (res.ok && !contentType.includes("text/html") && !contentType.includes("application/xhtml+xml")) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
async function initPipeline(config) {
|
|
130
|
+
if (asrPipeline) {
|
|
131
|
+
self.postMessage({ type: "READY" });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (isInitializing) return;
|
|
135
|
+
isInitializing = true;
|
|
136
|
+
env.useBrowserCache = typeof caches !== "undefined";
|
|
137
|
+
await sanitizeTransformersCache();
|
|
138
|
+
const modelId = config?.modelId || "onnx-community/whisper-base";
|
|
139
|
+
const soundBaseUrl = config?.soundBaseUrl || "/sounds/";
|
|
140
|
+
const remoteHost = config?.remoteHost || "https://hf-mirror.com";
|
|
141
|
+
const dtype = config?.dtype || "q8";
|
|
142
|
+
const hasLocal = await checkLocalModelExists(soundBaseUrl, modelId);
|
|
143
|
+
if (hasLocal) {
|
|
144
|
+
console.log(`[Whisper Worker] 检测到本地静态模型目录: ${soundBaseUrl}${modelId}`);
|
|
145
|
+
const normalizedUrl = soundBaseUrl.endsWith("/") ? soundBaseUrl : `${soundBaseUrl}/`;
|
|
146
|
+
env.allowLocalModels = true;
|
|
147
|
+
env.allowRemoteModels = false;
|
|
148
|
+
env.localModelPath = normalizedUrl;
|
|
149
|
+
} else {
|
|
150
|
+
console.log(`[Whisper Worker] 本地未检测到模型文件,将自镜像源 ${remoteHost} 加载/缓存模型...`);
|
|
151
|
+
env.allowLocalModels = false;
|
|
152
|
+
env.allowRemoteModels = true;
|
|
153
|
+
env.remoteHost = remoteHost;
|
|
154
|
+
env.remotePathTemplate = "{model}/resolve/{revision}/";
|
|
155
|
+
}
|
|
156
|
+
const progress_callback = (progressData) => {
|
|
157
|
+
self.postMessage({
|
|
158
|
+
type: "PROGRESS",
|
|
159
|
+
data: progressData
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
try {
|
|
163
|
+
const requestedDevice = config?.device || "wasm";
|
|
164
|
+
let device = "wasm";
|
|
165
|
+
if (requestedDevice === "webgpu" || requestedDevice === "auto") {
|
|
166
|
+
if (typeof navigator !== "undefined" && navigator.gpu) {
|
|
167
|
+
device = "webgpu";
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
console.log(`[Whisper Worker] 正在使用 ${device} 加载模型: ${modelId}...`);
|
|
172
|
+
asrPipeline = await pipeline("automatic-speech-recognition", modelId, {
|
|
173
|
+
device,
|
|
174
|
+
dtype,
|
|
175
|
+
progress_callback
|
|
176
|
+
});
|
|
177
|
+
} catch (gpuError) {
|
|
178
|
+
console.warn("[Whisper Worker] 指定设备初始化失败,自动降级为 WASM CPU:", gpuError);
|
|
179
|
+
device = "wasm";
|
|
180
|
+
asrPipeline = await pipeline("automatic-speech-recognition", modelId, {
|
|
181
|
+
device: "wasm",
|
|
182
|
+
dtype,
|
|
183
|
+
progress_callback
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
isInitializing = false;
|
|
187
|
+
self.postMessage({ type: "READY", device });
|
|
188
|
+
} catch (error) {
|
|
189
|
+
isInitializing = false;
|
|
190
|
+
console.error("[Whisper Worker] 模型初始化失败:", error);
|
|
191
|
+
self.postMessage({
|
|
192
|
+
type: "ERROR",
|
|
193
|
+
error: error.message || "语音模型加载失败,请检查网络或静态资源配置。"
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function enqueueTranscribe(data) {
|
|
198
|
+
transcribeQueue.push(data);
|
|
199
|
+
if (transcribeRunning) return;
|
|
200
|
+
transcribeRunning = true;
|
|
201
|
+
while (transcribeQueue.length) {
|
|
202
|
+
const next = transcribeQueue.shift();
|
|
203
|
+
await transcribeAudio(next);
|
|
204
|
+
}
|
|
205
|
+
transcribeRunning = false;
|
|
206
|
+
}
|
|
207
|
+
function getPeakAmplitude(audio) {
|
|
208
|
+
let maxVal = 0;
|
|
209
|
+
for (let i = 0; i < audio.length; i++) {
|
|
210
|
+
const abs = Math.abs(audio[i]);
|
|
211
|
+
if (abs > maxVal) maxVal = abs;
|
|
212
|
+
}
|
|
213
|
+
return maxVal;
|
|
214
|
+
}
|
|
215
|
+
async function transcribeAudio(data) {
|
|
216
|
+
if (!asrPipeline) {
|
|
217
|
+
self.postMessage({
|
|
218
|
+
type: "ERROR",
|
|
219
|
+
taskId: data?.taskId,
|
|
220
|
+
error: "语音识别引擎尚未就绪,请先初始化。"
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const {
|
|
225
|
+
taskId,
|
|
226
|
+
audio,
|
|
227
|
+
language = "chinese",
|
|
228
|
+
task = "transcribe",
|
|
229
|
+
chunkIndex = 0,
|
|
230
|
+
isFinal = true
|
|
231
|
+
} = data;
|
|
232
|
+
try {
|
|
233
|
+
self.postMessage({ type: "TRANSCRIBING", taskId, chunkIndex });
|
|
234
|
+
const peak = getPeakAmplitude(audio);
|
|
235
|
+
if (peak < 0.012) {
|
|
236
|
+
self.postMessage({
|
|
237
|
+
type: "RESULT",
|
|
238
|
+
taskId,
|
|
239
|
+
chunkIndex,
|
|
240
|
+
isFinal,
|
|
241
|
+
silent: true,
|
|
242
|
+
text: ""
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (peak > 0 && peak < 0.4) {
|
|
247
|
+
const gain = Math.min(3, 0.8 / peak);
|
|
248
|
+
for (let i = 0; i < audio.length; i++) {
|
|
249
|
+
audio[i] = Math.max(-1, Math.min(1, audio[i] * gain));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
let streamedText = "";
|
|
253
|
+
const generateOptions = {
|
|
254
|
+
language: language || "chinese",
|
|
255
|
+
task: task || "transcribe"
|
|
256
|
+
};
|
|
257
|
+
try {
|
|
258
|
+
const tokenizer = asrPipeline.tokenizer;
|
|
259
|
+
if (tokenizer) {
|
|
260
|
+
generateOptions.streamer = new WhisperTextStreamer(tokenizer, {
|
|
261
|
+
skip_prompt: true,
|
|
262
|
+
callback_function: (piece) => {
|
|
263
|
+
if (!piece) return;
|
|
264
|
+
streamedText += piece;
|
|
265
|
+
self.postMessage({
|
|
266
|
+
type: "PARTIAL",
|
|
267
|
+
taskId,
|
|
268
|
+
chunkIndex,
|
|
269
|
+
delta: piece,
|
|
270
|
+
text: streamedText
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
} catch (streamErr) {
|
|
276
|
+
console.warn("[Whisper Worker] 创建文本流失败,回退为整段输出:", streamErr);
|
|
277
|
+
}
|
|
278
|
+
const result = await asrPipeline(audio, generateOptions);
|
|
279
|
+
const text = (typeof result === "string" ? result : result?.text ?? streamedText ?? "").trim();
|
|
280
|
+
self.postMessage({
|
|
281
|
+
type: "RESULT",
|
|
282
|
+
taskId,
|
|
283
|
+
chunkIndex,
|
|
284
|
+
isFinal,
|
|
285
|
+
text
|
|
286
|
+
});
|
|
287
|
+
} catch (err) {
|
|
288
|
+
console.error("[Whisper Worker] 语音识别推理出错:", err);
|
|
289
|
+
self.postMessage({
|
|
290
|
+
type: "ERROR",
|
|
291
|
+
taskId,
|
|
292
|
+
chunkIndex: data?.chunkIndex,
|
|
293
|
+
isFinal: data?.isFinal,
|
|
294
|
+
error: `识别失败: ${err.message || err}`
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
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 .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 .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}/*!
|
|
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}}/*!
|
|
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-
|
|
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}
|
package/package.json
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@szjy/ai-coms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "vue3 ai component",
|
|
5
5
|
"main": "dist/index.umd.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"dist
|
|
9
|
+
"dist/index.mjs",
|
|
10
|
+
"dist/index.umd.js",
|
|
11
|
+
"dist/index.d.ts",
|
|
12
|
+
"dist/style.css",
|
|
13
|
+
"dist/packages",
|
|
14
|
+
"dist/images",
|
|
15
|
+
"dist/scripts/ai/whisper.worker.js",
|
|
16
|
+
"dist/scripts/ai/highlight.11.11.1.min.js",
|
|
17
|
+
"dist/scripts/ai/highlight.11.11.1.min.css",
|
|
18
|
+
"dist/scripts/ai/markdown-it.min.js",
|
|
19
|
+
"dist/scripts/ai/README.md"
|
|
10
20
|
],
|
|
11
21
|
"scripts": {
|
|
12
|
-
"dev": "vite",
|
|
13
|
-
"build": "vite build",
|
|
14
|
-
"build:dev": "vue-tsc --noEmit && vite build --mode dev",
|
|
22
|
+
"dev": "node scripts/build-voice-assets.mjs && vite",
|
|
23
|
+
"build": "node scripts/build-voice-assets.mjs && vite build",
|
|
24
|
+
"build:dev": "vue-tsc --noEmit && node scripts/build-voice-assets.mjs && vite build --mode dev",
|
|
25
|
+
"build:voice": "node scripts/build-voice-assets.mjs",
|
|
15
26
|
"preview": "vite preview",
|
|
16
27
|
"release": "npx commit-and-tag-version",
|
|
17
|
-
"sync": "cnpm sync @szjy/ai-coms"
|
|
28
|
+
"sync": "cnpm sync @szjy/ai-coms",
|
|
29
|
+
"model:download": "python scripts/download_model.py"
|
|
18
30
|
},
|
|
19
31
|
"dependencies": {
|
|
32
|
+
"@huggingface/transformers": "^3.3.3",
|
|
20
33
|
"aa-loader": "^0.1.5",
|
|
21
34
|
"element-plus": "2.7.1",
|
|
22
35
|
"vue": "^3.4.21"
|
package/dist/vite.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|