+
@@ -141,6 +147,11 @@
const speakingTimeInSeconds = speakingTime * 60;
return speakingTimeInSeconds;
}
+
+ // 映射的字段
+ function Reflection(str) {
+
+ }
@@ -152,7 +163,6 @@
bloodOxygen: "血氧",
bloodPressure: '血压',
bloodLiquid: "血脂",
- meiTuo: '梅脱',
pulseReat: '心率',
bodyTemperature: '体温',
ECGData: '心电图',
@@ -220,6 +230,9 @@
// 个人信息
var user = userInfo(JSON.parse(getURLParameter('user')));
+ var apitoken = getURLParameter('token');
+ var deviceId = getURLParameter('deviceId');
+
// 获取微软token
fetch("https://eastasia.api.cognitive.microsoft.com/sts/v1.0/issueToken", {
@@ -278,117 +291,107 @@
this.stop();
// voice.stop();
- const params = { msg: text }
+ const params = { msg: text };
- /*
- * 拿到匹配的文字下标
- */
-
- var QSindex = containsKeywordRegex(params.msg);
- if (QSindex == 0) {
- const obj = arrayOfObjects.filter(item => item.type == "bloodGlucose");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的血糖为${obj[0].data_msg}毫摩尔/升`
- } else {
- speed(`血糖数据为空, 请连接或同步设备数据`)
+ // 判断关键字是否存在
+ const result = parseHealthQuery(params.msg);
+ if (result) {
+ DetailDay(result.dataKey, result.date).then(res => {
+ let TargetData = res.data.data;
+
+ var QSindex = containsKeywordRegex(params.msg);
+
+ Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)},(data_msg为值,hour_minute为检测时间) #限制:回复用户的内容中不要出现Null。#限制:回复不要带英文,要都转化成汉语。#限制:监测结果为Null的数据不做分析回复。`
+
+ /*
+ * 调用接口 传递关键信息 文字转语音
+ */
+ const xhr = new XMLHttpRequest();
+ xhr.open('POST', 'http://sc2.agrimedia.cn:8787/api/user/ask', true);
+
+ /*
+ * 关键字转换
+ */
+ var data = JSON.stringify({
+ "messages": [
+ {"role": "system", "content": Question},
+ {"role": "user", "content": `请问我${Items[QSindex]}正常吗`}
+ ]
+ })
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ const chunk = xhr.responseText;
+ const str = extractStopEvent(chunk);
+
+ /*
+ * 微软接口识别
+ */
+ fetch("https://eastasia.tts.speech.microsoft.com/cognitiveservices/v1", {
+ method: 'POST',
+ headers: {
+ 'Authorization': 'Bearer ' + token,
+ 'Ocp-Apim-Subscription-Key': '58e9b39b8f6f48fe8d01f85b727ff737',
+ 'Content-Type': 'application/ssml+xml',
+ 'X-Microsoft-OutputFormat': 'audio-24khz-48kbitrate-mono-mp3'
+ },
+ responseType: 'arraybuffer',
+ body: `
+
+
+
+ ${filterString(str.output.text, ['*', ' '])}
+
+
+
+ `,
+ }).then(async(response) => {
+ const content_bytes = await response.arrayBuffer();
+ const blob = new Blob([content_bytes], { type: 'audio/mp3' });
+ const blobUrl = URL.createObjectURL(blob);
+
+ // 设置音频源
+ audioElement.src = blobUrl;
+
+ // 播放音频
+ audioElement.play();
+
+ // 循环视频
+ replayVideoSegment(60, 120);
+
+ // 计算所需时间
+ const speakingTime = calculateSpeakingTime(content.data.choices[0].text);
+
+ // 开始倒计时
+ var totalTime = speakingTime;
+ var countdown = setInterval(function() {
+ // 更新剩余时间
+ totalTime --;
+ if (totalTime <= 0) {
+ // 停止倒计时
+ clearInterval(countdown);
+ replayVideoSegment(0, 60);
+ }
+ }, 1000);
+
+ hideModal()
+ }).catch(e => {
+ hideModal();
+ });
+
+ startRec.style.display = 'block';
+ runRec.style.display = 'none';
+ endRec.style.opacity = 'none';
+ }
+ };
+ xhr.send(data);
+ isCallbackExecuted = true;
return
- }
- }
-
-
- if (QSindex == 1) {
- const obj = arrayOfObjects.filter(item => item.type == "SleepDatas");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近睡眠时长为${minutesToHoursMinutesStringSimplified(obj[0].data_msg[0].sleepTotalTime)}分钟`
- } else {
- speed(`睡眠数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 2) {
- const obj = arrayOfObjects.filter(item => item.type == "bloodOxygen");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的血氧为${obj[0].data_msg}毫摩尔/升`
- } else {
- speed(`血氧数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 3) {
- const obj = arrayOfObjects.filter(item => item.type == "bloodPressure");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的血压为${obj[0].data_msg.bloodPressureLow}/${obj[0].data_msg.bloodPressureHigh}毫摩尔/升`
- } else {
- speed(`血压数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 4 || QSindex == 11) {
- const obj = arrayOfObjects.filter(item => item.type == "bloodLiquid");
- if (obj[0].data_msg.cholesterol) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的血脂状况为,
- 尿酸为${obj[0].data_msg.uricAcidVal/10},
- 总胆固醇为${obj[0].data_msg.cholesterol/100},
- 甘油三酯为${obj[0].data_msg.triacylglycerol/100},
- 高密度脂蛋白为${obj[0].data_msg.highDensity/100},
- 低密度脂蛋白为${obj[0].data_msg.lowDensity/100}, `
- } else {
- speed(`血脂数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 6) {
- const obj = arrayOfObjects.filter(item => item.type == "pulseReat");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的心率为${obj[0].data_msg[0]}, `
- } else {
- speed(`心率数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 7) {
- const obj = arrayOfObjects.filter(item => item.type == "bodyTemperature");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的体温为${obj[0].data_msg}摄氏度`
- } else {
- speed(`体温数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 8) {
- const obj = arrayOfObjects.filter(item => item.type == "ECGData");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近心电图测量结果为${obj[0].data_msg.heartRate}次/分`
- } else {
- speed(`心电图数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 9) {
- const obj = arrayOfObjects.filter(item => item.type == "bodyData");
- if (obj[0].data_msg.BMI) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近身体成分结果为${obj[0].data_msg.BMI}`
- } else {
- speed(`身体成分数据为空, 请连接或同步设备数据`)
- return
- }
- }
- if (QSindex == 10) {
- const obj = arrayOfObjects.filter(item => item.type == "stepIndex");
- if (obj[0].data_msg) {
- Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的运动为${obj[0].data_msg.step}步数,
- ${obj[0].data_msg.calorie/10}千卡,
- ${obj[0].data_msg.distance/1000}公里`
- } else {
- speed(`运动数据为空, 请连接或同步设备数据`)
- return
- }
- }
-
- if (QSindex == 99999) {
+ })
+ } else {
+ // 如果不存在关键字,就直接走下面
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://sc2.agrimedia.cn:8787/api/user/ask', true);
-
var data = JSON.stringify({
"messages": [
{"role": "system", "content": params.msg},
@@ -427,91 +430,8 @@
const blob = new Blob([content_bytes], { type: 'audio/mp3' });
const blobUrl = URL.createObjectURL(blob);
- // 设置音频源
- audioElement.src = blobUrl;
-
- // 播放音频
- audioElement.play();
-
- // 循环视频
- replayVideoSegment(60, 120);
-
- // 计算所需时间
- const speakingTime = calculateSpeakingTime(content.data.choices[0].text);
-
- // 开始倒计时
- var totalTime = speakingTime;
- var countdown = setInterval(function() {
- // 更新剩余时间
- totalTime --;
- if (totalTime <= 0) {
- // 停止倒计时
- clearInterval(countdown);
- replayVideoSegment(0, 60);
- }
- }, 1000);
-
- hideModal()
- }).catch(e => {
- hideModal();
- });
-
- startRec.style.display = 'block';
- runRec.style.display = 'none';
- // endRec.style.opacity = 0;
- }
- };
- xhr.send(data);
- isCallbackExecuted = true;
- return
- } else {
- /*
- * 调用接口 传递关键信息 文字转语音
- */
- const xhr = new XMLHttpRequest();
- xhr.open('POST', 'http://sc2.agrimedia.cn:8787/api/user/ask', true);
-
-
- /*
- * 关键字转换
- */
- var data = JSON.stringify({
- "messages": [
- {"role": "system", "content": Question},
- {"role": "user", "content": `请问我${Items[QSindex]}正常吗`}
- ]
- })
-
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4) {
- const chunk = xhr.responseText;
- const str = extractStopEvent(chunk);
-
- /*
- * 微软接口识别
- */
- fetch("https://eastasia.tts.speech.microsoft.com/cognitiveservices/v1", {
- method: 'POST',
- headers: {
- 'Authorization': 'Bearer ' + token,
- 'Ocp-Apim-Subscription-Key': '58e9b39b8f6f48fe8d01f85b727ff737',
- 'Content-Type': 'application/ssml+xml',
- 'X-Microsoft-OutputFormat': 'audio-24khz-48kbitrate-mono-mp3'
- },
- responseType: 'arraybuffer',
- body: `
-
-
-
- ${filterString(str.output.text, ['*', ' '])}
-
-
-
- `,
- }).then(async(response) => {
- const content_bytes = await response.arrayBuffer();
- const blob = new Blob([content_bytes], { type: 'audio/mp3' });
- const blobUrl = URL.createObjectURL(blob);
+ // 字幕文字
+ voiceTxt.value = filterString(str.output.text, ['*', ' ']);
// 设置音频源
audioElement.src = blobUrl;
@@ -544,7 +464,7 @@
startRec.style.display = 'block';
runRec.style.display = 'none';
- // endRec.style.opacity = 0;
+ endRec.style.opacity = 'none';
}
};
xhr.send(data);
@@ -557,6 +477,22 @@
}
});
+ // 暂停
+ runRec.addEventListener("click", function() {
+ voiceTxt.value = '';
+ voice.start();
+ isCallbackExecuted = false;
+
+ // 先静音即可处理解决(提前做交互)
+ audioElement.muted = false;
+ audioElement.pause();
+
+ startRec.style.display = 'none';
+ runRec.style.display = 'block';
+ endRec.style.display = 'none';
+ showModal()
+ });
+
// 开始识别
startRec.addEventListener("click", function() {
@@ -572,7 +508,7 @@
startRec.style.display = 'none';
runRec.style.display = 'block';
- // endRec.style.opacity = 0;
+ endRec.style.display = 'none';
showModal()
});
@@ -610,7 +546,38 @@
modal.style.display = 'none';
dialog.style.display = 'none';
}
+
+ // 查询详情数据
+ async function DetailDay(type, data) {
+ try {
+ // const response = await fetch('https://test.sc2.agrimedia.cn/watch/device/getDeviceListDays', {
+ const response = await fetch('https://ai.agrimedia.cn/watch/device/getDeviceListDays', {
+ method: 'POST',
+ headers: {
+ 'ApiToken': apitoken,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ "device_real_time": data,
+ "device_id": deviceId,
+ "type": type
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error('Network response was not ok: ' + response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ console.error('There was a problem with your fetch operation:', error);
+ throw error; // 可选:重新抛出错误以便上层可以捕获并处理
+ }
+ }
+
+ // 语音输出
function speed(str) {
fetch("https://eastasia.tts.speech.microsoft.com/cognitiveservices/v1", {
method: 'POST',
@@ -635,6 +602,9 @@
const blob = new Blob([content_bytes], { type: 'audio/mp3' });
const blobUrl = URL.createObjectURL(blob);
+ // 字幕文字
+ voiceTxt.value = str;
+
// 设置音频源
audioElement.src = blobUrl;
@@ -707,7 +677,60 @@
// 个人信息
function userInfo(user) {
- return `年龄${user.birthday}, 身高${user.height}, 体重${user.weight}`
+ if (user) {
+ return `年龄${user.birthday}, 身高${user.height}, 体重${user.weight}`
+ }
+ }
+
+ // 解析文字
+ function parseHealthQuery(query, demoData) {
+ if (!demoData) {
+ demoData = {
+ bloodGlucose: "血糖",
+ SleepDatas: "睡眠",
+ bloodOxygen: "血氧",
+ bloodPressure: '血压',
+ bloodLiquid: "血脂",
+ meiTuo: '梅脱',
+ pulseReat: '心率',
+ bodyTemperature: '体温',
+ ECGData: '心电图',
+ bodyData: '身体成份',
+ stepIndex: '运动'
+ };
+ }
+
+ // 获取当前日期
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = today.getMonth() + 1; // 月份从0开始,所以需要+1
+ const day = today.getDate();
+
+ // 初始化日期为今天
+ let targetDate = new Date(year, month, day);
+
+ // 检查时间词并设置目标日期
+ if (query.includes("昨天")) {
+ targetDate.setDate(day - 1);
+ } else if (query.includes("前天")) {
+ targetDate.setDate(day - 2);
+ }
+
+ // 格式化日期为 YYYY-MM-DD
+ const formattedDate = `${targetDate.getFullYear()}-${('0' + targetDate.getMonth()).slice(-2)}-${('0' + targetDate.getDate()).slice(-2)}`;
+
+ // 查找匹配的数据项键
+ for (let key in demoData) {
+ if (query.includes(demoData[key])) {
+ return {
+ dataKey: key,
+ date: formattedDate
+ };
+ }
+ }
+
+ // 如果没有找到匹配的数据项,则返回null或错误信息(这里选择返回null)
+ return null;
}
};
@@ -721,7 +744,7 @@
width: 100%;
height: 100vh;
overflow: hidden;
- background-image: url('https://img.agrimedia.cn/bmsc/index/ai-persion-bg-tuya.jpeg');
+ background-image: url('https://img.agrimedia.cn/bmsc/bg-cideo-tuya.png');
background-size: 100% 100%;
display: flex;
flex-direction: column;
@@ -734,7 +757,7 @@
width: 80%;
top: 10%;
height: auto;
- background-image: url('https://img.agrimedia.cn/bmsc/index/video-bg.png');
+ background-image: url('https://img.agrimedia.cn/bmsc/bg-cideo-tuya.png');
background-size: 100% 100%;
margin: 0 auto;
padding: 20px;
@@ -768,6 +791,20 @@
height: 30px;
}
+ .status > .btn {
+ text-align: center;
+ font-size: 30px;
+ color: #fff;
+ }
+
+ .buttons {
+ border: 2px solid #fff;
+ color: #fff;
+ font-size: 28px;
+ padding: 4px 20px;
+ border-radius: 5px;
+ }
+
/* 遮罩样式 */
.overlay {
position: fixed;
@@ -910,6 +947,27 @@
font-weight: 800;
}
+ .voice {
+ position: fixed;
+ bottom: 0px;
+ width: 100%;
+ background-color: #000;
+ }
+ .voice-box {
+ width: 100%;
+ animation: textRoll linear 10s infinite; // 文字滚动动画
+ white-space: nowrap; // 文字不换行
+ }
+
+ @keyframes textRoll {
+ 0% {
+ transform: translateX(100%);
+ }
+
+ 100% {
+ transform: translateX(-100%);
+ }
+ }