<template>
	<view class="">
		<!-- <button class="btn" shape="circle" type="info" @touchstart="openMedia" @touchend="stopMedia">按住
			说话</button> -->
		<!-- @click="handleShow" -->
		<!-- <iatPopup v-model:moduleValue="show" /> -->
		<!-- <view v-if="show" class="iating">
			正在说话中....
		</view> -->
	</view>
</template>

<script>
	import CryptoJS from "crypto-js";
	// 科大讯飞接口配置
	const config = {
		hostUrl: "wss://iat-api.xfyun.cn/v2/iat",
		host: "iat-api.xfyun.cn",
		appid: "331874e7",
		apiSecret: "YTc3MDJmYjJjMjk3NTJhMGMzMTk5YTVl", //"你的秘钥",
		apiKey: "ddf92cc17ecc9cda0a8cca5d4997e897", //"你的apikey",
		uri: "/v2/iat",
		highWaterMark: 1280,
		// file: "./16k_10.pcm",
	};
	// 鉴权签名
	function getAuthStr(date) {
		let signatureOrigin = `host: ${config.host}\ndate: ${date}\nGET ${config.uri} HTTP/1.1`;
		let signatureSha = CryptoJS.HmacSHA256(signatureOrigin, config.apiSecret);
		let signature = CryptoJS.enc.Base64.stringify(signatureSha);
		let authorizationOrigin =
			`api_key="${config.apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signature}"`;
		let authStr = CryptoJS.enc.Base64.stringify(
			CryptoJS.enc.Utf8.parse(authorizationOrigin)
		);
		return authStr;
	}

	function getUrl() {
		// 获取当前时间 RFC1123格式
		let date = new Date().toUTCString();
		//科大讯飞远程连接地址
		let wssUrl =
			config.hostUrl +
			"?authorization=" +
			getAuthStr(date) +
			"&date=" +
			encodeURIComponent(date) +
			"&host=" +
			config.host;
		console.log("websocke科大讯飞的地址为", wssUrl);
		return wssUrl;
	}
	let uniSocketTask = null
	//发送给科大讯飞的第一帧的模板数据格式
	let frame = {
		common: {
			app_id: config.appid,
		},
		business: {
			language: "zh_cn",
			domain: "iat",
			accent: "mandarin",
			dwa: "wpgs", // 可选参数，动态修正
			vad_eos: 5000,
		},
		data: {
			status: 0,
			format: "audio/L16;rate=16000",
			encoding: "lame"
		},
	};

	// 录音配置项
	const recordOption = {
		sampleRate: 16000, // 采样率（pc不支持）
		format: "mp3", // 音频格式，默认是 aac
	};
	// 录音管理器
	const recordManager = uni.getRecorderManager();
	console.log('recordManager:', recordManager)


	export default {
		data() {
			return {
				show: false,
				resultText: "",
				resultTextTemp: "",
				renderText: "",
			}
		},
		onLoad() {

		},
		onShow() {

		},
		methods: {
			//打开麦克风
			openMedia() {
				this.connectSocket(); //创建websocket连接
			},
			stopMedia() {
				console.log('组件录音结束',)
				recordManager.stop()
			},
			//创建连接并返回数据
			connectSocket() {
				//创建socketTask实例
				if (uniSocketTask === null) {
					uniSocketTask = uni.connectSocket({
						url: getUrl(),
						success() {},
					});
					console.log('uniSocketTask:::', uniSocketTask)
					//监听连接成功的事件
					uniSocketTask.onOpen(() => {
						console.log("监听到开启连接成功");
						this.startRecord(); //打开录音
					});
					//监听连接关闭的事件
					uniSocketTask.onClose((res) => {
						console.log("监听到关闭连接成功", res); //Websocket关闭!服务器读取MSG超时
						uniSocketTask = null;
					});
					uniSocketTask.onError((res) => {
						console.log("监听到连接发生错误", res);
					});
					//监听科大讯飞消息返回
					uniSocketTask.onMessage((res) => {
						//收到消息
						console.log('收到消息:', res)
						const message = JSON.parse(res.data);
						//判断是否存在数据
						if (res.data) {
							console.log("收到服务器消息,并开始渲染", message);
							this.renderResult(message);

							if (message.code === 0 && message.data.status === 2) {
								//该函数为当前页唯一的关闭连接函数
								console.log('最后一条', this.renderText)
								this.closeSocket();
								this.$emit('renderText', this.renderText)
							}
							//收到不正常服务器消息,返回错误到控制台
							if (message.code !== 0) {
								this.closeSocket();
								console.error(message);
							}
						} else {
							console.log("未监听到消息：原因：", JSON.stringify(res));
						}
					});
				} else {
					console.log("socketTask实例已存在");
				}
			},
			//发送消息
			sendMessage(sendData) {
				console.log('发送', JSON.stringify(sendData))
				uniSocketTask.send({
					data: JSON.stringify(sendData),
					success() {
						console.log("发送成功");
					},
					fail() {
						console.log("发送失败");
					},
				});
			},
			//关闭连接
			closeSocket() {
				console.log("开始尝试关闭连接");
				// 关闭连接
				uniSocketTask.close();
			},
			//开启录音
			startRecord() {
				console.log("打开录音");
				recordManager.onStart(() => {
					console.log("开始录音");
					this.show = true
					// ...
				});
				recordManager.onStop((res) => {
					this.show = false
					// tempFilePath	String	录音文件的临时路径
					console.log("录音停止,文件路径为:", res.tempFilePath);

					// this.sendMessage(frame)

					this.pathToBase64(res.tempFilePath).then(base64 => {
						console.log('base64--', base64);
						// 这里一定要注意：当需要将base64字符串转换为Buffer时，通常会去掉前面部分的数据URL标识（如"data:image/png;base64,"），因为这部分内容不是实际的base64编码数据。
						let buff = base64.split(",")[1]
						const arrayBuffer = uni.base64ToArrayBuffer(buff)
						const audioString = this.toString(arrayBuffer)
						console.log("文件读取成功", audioString.length);
						let offset = 0;
						while (offset < audioString.length) {
							const subString = audioString.substring(offset, offset + 1280)
							offset += 1280
							const isEnd = offset >= audioString.length

							let params = {
								common: {
									app_id: config.appid,
								},
								business: {
									language: "zh_cn",
									domain: "iat",
									accent: "mandarin",
									dwa: "wpgs", // 可选参数，动态修正
									vad_eos: 5000,
								},
								data: {
									status: isEnd ? 2 : 1,
									format: "audio/L16;rate=16000",
									encoding: "lame",
									audio: btoa(subString)
								}
							}

							this.sendMessage(params);
						}
					}).catch(error => {
						console.error(error)
					})

				});
				recordManager.onError((err) => {
					// errMsg	String	错误信息
					console.log("录音出现错误", err);
				});

				recordManager.start(recordOption);
			},
			//关闭录音
			stopRecord() {
				recordManager.stop();
			},
			toString(buffer) {
				var binary = '';
				var bytes = new Uint8Array(buffer);
				var len = bytes.byteLength;
				for (var i = 0; i < len; i++) {
					binary += String.fromCharCode(bytes[i]);
				}
				return binary
			},
			//录音文件路径转base64
			pathToBase64(path) {
				return new Promise(function(resolve, reject) {
					// app
					if (typeof plus === 'object') {
						plus.io.resolveLocalFileSystemURL(path, function(entry) {
							entry.file(function(file) {
								var fileReader = new plus.io.FileReader()
								fileReader.onload = function(evt) {
									resolve(evt.target.result)
								}
								fileReader.onerror = function(error) {
									reject(error)
								}
								fileReader.readAsDataURL(file)
							}, function(error) {
								reject(error)
							})
						}, function(error) {
							reject(error)
						})

						return
					}

					reject(new Error('not support'))
				})
			},
			//讯飞回复字段拼接
			renderResult(jsonData) {
				console.log("开始执行渲染函数", jsonData);
				if (jsonData.data && jsonData.data.result) {
					let data = jsonData.data.result;
					let str = ""; // 初始化一个字符串变量用于存储拼接后的识别结果
					let ws = data.ws;
					for (let i = 0; i < ws.length; i++) {
						str = str + ws[i].cw[0].w;
					}
					// 开启wpgs会有此字段(前提：在控制台开通动态修正功能)
					// 取值为 "apd"时表示该片结果是追加到前面的最终结果；取值为"rpl" 时表示替换前面的部分结果，替换范围为rg字段
					if (data.pgs) {
						if (data.pgs === "apd") {
							// 将resultTextTemp同步给resultText
							this.resultText = this.resultTextTemp;
						}
						// 将结果存储在resultTextTemp中
						this.resultTextTemp = this.resultText + str;
					} else {
						this.resultText = this.resultText + str;
					}
					this.renderText = this.resultTextTemp || this.resultText || "";
				}
				console.log("渲染后的数据为");
				console.log(this.renderText);
			},
		}
	}
</script>

<style>
	page {
		/* background-color: #111111; */
	}
</style>
<style lang="scss" scoped>

</style>