Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/main'

# Conflicts:
#	src/api/Recognition.ts
#	src/views/fanyi/components/textComponent.vue
#	src/views/knowledge/index.vue
ageer 1 mēnesi atpakaļ
vecāks
revīzija
471451b879
2 mainītis faili ar 745 papildinājumiem un 174 dzēšanām
  1. 594 0
      pnpm-lock.yaml
  2. 151 174
      src/api/Recognition.ts

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 594 - 0
pnpm-lock.yaml


+ 151 - 174
src/api/Recognition.ts

@@ -1,188 +1,165 @@
 import { mlog } from "./mjapi";
 
-export interface recType {
-	timeOut: number;
-	asrLanguage?: string;
-	listener?: (result: string) => void;
-	onEnd?: () => void;
-	onStart?: () => void;
+export interface recType{
+    timeOut:number
+    asrLanguage?:string
+    listener?: (result: string) => void
+    onEnd?: () => void
+    onStart?: () => void
 }
 export class Recognition {
-	private recognition: any;
-	private listener?: (result: string) => void;
-	private isStop = false;
-	private recOpt: recType = { timeOut: 2000 };
-	private handleTime: any;
-	private hTime: Date | undefined;
-	private asrLanguage = "cmn-Hans-CN";
-	private onEnd?: () => void;
-	private onStart?: () => void;
-
-	public setListener(fn: (result: string) => void) {
-		this.listener = fn;
-		return this;
-	}
-
-	public setOnEnd(fn: () => void) {
-		this.onEnd = fn;
-		return this;
-	}
-
-	public setOpt(opt: recType) {
-		this.recOpt = opt;
-		if (opt.listener) this.setListener(opt.listener);
-		if (opt.onEnd) this.setOnEnd(opt.onEnd);
-		if (opt.asrLanguage) this.setLang(opt.asrLanguage);
-		if (opt.onStart) this.onStart = opt.onStart;
-		return this;
-	}
-
-	public setLang(lang: string) {
-		this.asrLanguage = lang;
-		return this;
-	}
-
-	public start() {
-		this.isStop = false;
-		if (
-			typeof window === "undefined" ||
-			(!window.SpeechRecognition && !window.webkitSpeechRecognition)
-		) {
-			console.warn("当前浏览器不支持 SpeechRecognition,请使用 Chrome 或 Edge");
-			return;
-		}
-
-		if (!this.recognition) {
-			const recognition = new (window.SpeechRecognition ||
-				window.webkitSpeechRecognition)();
-			this.recognition = recognition;
-		}
-		const recognition = this.recognition;
-
-		recognition.interimResults = true;
-		recognition.lang = this.asrLanguage;
-		recognition.continuous = true;
-
-		this.hTime = new Date();
-		this.handleTime = setInterval(() => this.check(this), this.recOpt.timeOut);
-
-		recognition.addEventListener("result", (event: any) => {
-			let transcript = "";
-			for (let index = 0; index < event.results.length; index++) {
-				const item = event.results[index];
-				if (transcript && this.asrLanguage.includes("Han")) transcript += ",";
-				transcript += (item as unknown as SpeechRecognitionAlternative[])[0]
-					?.transcript;
-			}
-			if (!transcript) return;
-			this.hTime = new Date();
-			this.listener?.(transcript);
-		});
-
-		recognition.addEventListener("end", () => {
-			if (this.isStop) {
-				clearInterval(this.handleTime);
-				return;
-			}
-			setTimeout(() => recognition.start(), 1000);
-		});
-
-		recognition.start();
-		this.onStart?.();
-		return this;
-	}
-
-	private check(that: Recognition) {
-		if (!that.hTime) return;
-		const dt = new Date().getTime() - that.hTime.getTime();
-		if (dt > that.recOpt.timeOut) {
-			that.stop(); // 只在 stop 中触发 onEnd
-		}
-	}
-
-	public stop() {
-		if (this.isStop) return this; // 如果已经停止,直接返回
-		this.isStop = true;
-		this.recognition?.stop();
-		clearInterval(this.handleTime);
-		this.onEnd?.(); // 只在这里触发一次 onEnd
-		return this;
-	}
-
-	// public stop() {
-	//   this.isStop = true;
-	//   this.recognition?.stop();
-	//   return this;
-	// }
-
-	// private check(that: Recognition) {
-	//   if (!that.hTime) return;
-	//   const dt = new Date().getTime() - that.hTime.getTime();
-	//   if (dt > that.recOpt.timeOut) that.stop();
-	// }
+  private recognition: any;
+  private listener?: (result: string) => void;
+  private isStop = false;
+  private recOpt: recType = { timeOut: 2000 };
+  private handleTime: any;
+  private hTime: Date | undefined;
+  private asrLanguage = "cmn-Hans-CN";
+  private onEnd?: () => void;
+  private onStart?: () => void;
+
+  public setListener(fn: (result: string) => void) {
+    this.listener = fn;
+    return this;
+  }
+
+  public setOnEnd(fn: () => void) {
+    this.onEnd = fn;
+    return this;
+  }
+
+  public setOpt(opt: recType) {
+    this.recOpt = opt;
+    if (opt.listener) this.setListener(opt.listener);
+    if (opt.onEnd) this.setOnEnd(opt.onEnd);
+    if (opt.asrLanguage) this.setLang(opt.asrLanguage);
+    if (opt.onStart) this.onStart = opt.onStart;
+    return this;
+  }
+
+  public setLang(lang: string) {
+    this.asrLanguage = lang;
+    return this;
+  }
+
+  public start() {
+    this.isStop = false;
+    if (typeof window === "undefined" || (!window.SpeechRecognition && !window.webkitSpeechRecognition)) {
+      console.warn("当前浏览器不支持 SpeechRecognition,请使用 Chrome 或 Edge");
+      return;
+    }
+
+    if (!this.recognition) {
+      const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
+      this.recognition = recognition;
+    }
+    const recognition = this.recognition;
+
+    recognition.interimResults = true;
+    recognition.lang = this.asrLanguage;
+    recognition.continuous = true;
+
+    this.hTime = new Date();
+    this.handleTime = setInterval(() => this.check(this), this.recOpt.timeOut);
+
+    recognition.addEventListener("result", (event: any) => {
+      let transcript = "";
+      for (let index = 0; index < event.results.length; index++) {
+        const item = event.results[index];
+        if (transcript && this.asrLanguage.includes("Han")) transcript += ",";
+        transcript += (item as unknown as SpeechRecognitionAlternative[])[0]?.transcript;
+      }
+      if (!transcript) return;
+      this.hTime = new Date();
+      this.listener?.(transcript);
+    });
+
+    recognition.addEventListener("end", () => {
+      if (this.isStop) {
+        this.onEnd?.();
+        clearInterval(this.handleTime);
+        return;
+      }
+      setTimeout(() => recognition.start(), 1000); // 避免 Mac 触发安全限制
+    });
+
+    recognition.start();
+    this.onStart?.();
+    return this;
+  }
+
+  public stop() {
+    this.isStop = true;
+    this.recognition?.stop();
+    return this;
+  }
+
+  private check(that: Recognition) {
+    if (!that.hTime) return;
+    const dt = new Date().getTime() - that.hTime.getTime();
+    if (dt > that.recOpt.timeOut) that.stop();
+  }
 }
 
+
 export const supportLanguages: Record<string, string> = {
-	"cmn-Hans-CN": "普通话 (中国大陆)",
-	"cmn-Hans-HK": "普通话 (香港)",
-	"yue-Hant-HK": "粵語 (香港)",
-	"en-US": "English(United States)",
-	"en-GB": "English(United Kingdom)",
-	"en-IN": "English(India)",
-	"es-ES": "Español",
-	"fr-FR": "Français",
-	"de-DE": "Deutsch",
-	"it-IT": "Italiano",
-	"ja-JP": "日本語",
-	"ko-KR": "한국어",
-	"ar-SA": "العربية",
-	"pt-BR": "Português",
-	"ru-RU": "Русский",
-	"nl-NL": "Nederlands",
-	"tr-TR": "Türkçe",
-	"sv-SE": "Svenska",
-	"hi-IN": "हिन्दी",
-	"el-GR": "Ελληνικά",
-	"he-IL": "עברית",
-	"id-ID": "Bahasa Indonesia",
-	"pl-PL": "Polski",
-	"th-TH": "ไทย",
-	"cs-CZ": "Čeština",
-	"hu-HU": "Magyar",
-	"da-DK": "Dansk",
-	"fi-FI": "Suomi",
-	"no-NO": "Norsk",
-	"sk-SK": "Slovenčina",
-	"uk-UA": "Українська",
-	"vi-VN": "Tiếng Việt",
+  'cmn-Hans-CN': '普通话 (中国大陆)',
+  'cmn-Hans-HK': '普通话 (香港)',
+  'yue-Hant-HK': '粵語 (香港)',
+  'en-US': 'English(United States)',
+  'en-GB': 'English(United Kingdom)',
+  'en-IN': 'English(India)',
+  'es-ES': 'Español',
+  'fr-FR': 'Français',
+  'de-DE': 'Deutsch',
+  'it-IT': 'Italiano',
+  'ja-JP': '日本語',
+  'ko-KR': '한국어',
+  'ar-SA': 'العربية',
+  'pt-BR': 'Português',
+  'ru-RU': 'Русский',
+  'nl-NL': 'Nederlands',
+  'tr-TR': 'Türkçe',
+  'sv-SE': 'Svenska',
+  'hi-IN': 'हिन्दी',
+  'el-GR': 'Ελληνικά',
+  'he-IL': 'עברית',
+  'id-ID': 'Bahasa Indonesia',
+  'pl-PL': 'Polski',
+  'th-TH': 'ไทย',
+  'cs-CZ': 'Čeština',
+  'hu-HU': 'Magyar',
+  'da-DK': 'Dansk',
+  'fi-FI': 'Suomi',
+  'no-NO': 'Norsk',
+  'sk-SK': 'Slovenčina',
+  'uk-UA': 'Українська',
+  'vi-VN': 'Tiếng Việt',
 };
 
 function sleep(time: number) {
-	return new Promise((resolve) => setTimeout(resolve, time));
+  return new Promise((resolve) => setTimeout(resolve, time));
 }
 
 //浏览器文字播放
-export async function speakText(
-	content: string,
-	callback: (playing: boolean) => void
-) {
-	if (!window.speechSynthesis) return;
-	if (speechSynthesis.speaking) {
-		speechSynthesis.cancel();
-		callback(false);
-	}
-
-	await sleep(300);
-
-	const msg = new SpeechSynthesisUtterance(content);
-	msg.lang = "zh";
-	msg.rate = 1;
-	msg.addEventListener("end", () => {
-		callback(false);
-	});
-	msg.addEventListener("error", () => {
-		callback(false);
-	});
-	callback(true);
-	speechSynthesis.speak(msg);
+export async function speakText(content: string, callback: (playing: boolean) => void) {
+  if (!window.speechSynthesis) return;
+  if (speechSynthesis.speaking) {
+    speechSynthesis.cancel();
+    callback(false);
+  }
+
+  await sleep(300);
+
+  const msg = new SpeechSynthesisUtterance(content);
+  msg.lang = 'zh';
+  msg.rate = 1;
+  msg.addEventListener('end', () => {
+    callback(false);
+  });
+  msg.addEventListener('error', () => {
+    callback(false);
+  });
+  callback(true);
+  speechSynthesis.speak(msg);
 }

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels