Compare commits

...

10 Commits

Author SHA1 Message Date
whitechiina d53d1e71cb updata 2025-05-14 15:49:38 +08:00
靳耀伟 c8aaa1e31a fix: 语音识别拼音 2024-11-01 14:11:04 +08:00
white 3d55fca864 style: 布局 2024-10-29 16:50:46 +08:00
white d611345b7a fix: 修复部分问题 2024-10-24 17:57:34 +08:00
white c92aef2d25 fix: 修复loading 2024-10-23 16:53:08 +08:00
white e0141f1cf2 fix: 处理屏幕初始化问题 2024-10-23 13:45:32 +08:00
white 91e4a89ae3 fix: 处理屏幕初始化问题 2024-10-23 13:45:06 +08:00
white 392157111c fix: 修复问题 2024-10-21 09:37:52 +08:00
white eef3f742eb fix: 修复状态 2024-10-17 14:01:59 +08:00
white b9dd70b658 fix: 刷新页面处理 2024-10-17 10:30:23 +08:00
75 changed files with 5452 additions and 3680 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -16,7 +16,7 @@
"type" : "uniCloud"
},
{
"playground" : "custom",
"playground" : "standard",
"type" : "uni-app:app-android"
}
]

9
AndroidManifest.xml Normal file
View File

@ -0,0 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="uni.UNI24DA8DD">
<!--permissions-->
<application>
<!--meta-data-->
<activity android:name="io.dcloud.PandoraEntryActivity" android:screenOrientation="landscape" />
</application>
</manifest>

25
App.vue
View File

@ -1,15 +1,12 @@
<script>
import Vue from 'vue'
export default {
created() {
},
export default {
onLoad() {
uni.onNetworkStatusChange((res) => {
console.log('网络类型变化:', res.networkType);
console.log('连接网络状态变化:', res.isConnected ? '已连接' : '断开连接');
});
// uni.onNetworkStatusChange((res) => {
// console.log(':', res.networkType);
// console.log(':', res.isConnected ? '' : '');
// });
},
onLaunch: async function() {
// APP
@ -57,18 +54,8 @@
console.log(res.isConnected);
console.log(res.networkType);
});
//
if (this.$store.getters['api/getApiToken']) {
setTimeout(() => {
uni.reLaunch({
url: '/pages/index/index'
})
}, 1000)
}
},
onHide: function() {
console.log('App 关闭')
},
methods: {
@ -151,7 +138,7 @@
}
body{
background: #fff !important;
background: #fff !important;
}
</style>

BIN
components/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -22,7 +22,18 @@
<view :class="'list'" v-for="(item, index) in dataList" :key="index" @click="goInfo(index)">
<view v-if="!customType.includes(activeType)" class="row" >
<view class="data">
<image src="https://img.agrimedia.cn/apptest/%E6%89%8B%E8%A1%A8-%E7%BA%BF%E6%80%A73-0.png" mode="widthFix"></image>
<image class="data-icon" src="https://img.agrimedia.cn/apptest/%E6%89%8B%E8%A1%A8-%E7%BA%BF%E6%80%A73-0.png" mode="widthFix"></image>
<view v-if="activeType == 'SleepDatas'">
<view>睡眠时长:
{{getHours(item.data_msg[0].sleepTotalTime, 0)}}
<text class="unit"></text>
{{getHours(item.data_msg[0].sleepTotalTime, 1)}}
<text class="unit"></text>
</view>
<view>深度睡眠: {{item.data_msg[0].deepSleepTime}}
<text class="unit">分钟</text>
</view>
</view>
<view v-if="activeType == 'stepIndex'">
步数{{item.data_msg.stepCount}}
</view>
@ -70,7 +81,7 @@
</view>
</view>
<view class="time">
{{item.date_str}} {{item.hour_minute}}
{{item.date_str}} {{item.hour_minute}}
</view>
</view>
<view class="" v-else>
@ -134,7 +145,8 @@
ECGData: '心电图',
stepIndex: '步数',
bodyData:'身体成分',
bloodLiquidAll: '血脂'
bloodLiquidAll: '血脂',
SleepDatas: '睡眠'
},
time: new Date().toISOString().substring(0, 10),
flag: true,
@ -191,6 +203,8 @@
type = 'step_split'
} else if (this.activeType == 'bloodLiquidAll') {
type = 'bloodLiquid'
} else if (this.activeType == 'SleepDatas') {
type = 'SleepDatas'
} else {
type = this.activeType
};
@ -221,11 +235,26 @@
},
back() {
if (this.activeType == 'ECGData' || this.activeType == 'bodyData') {
if (this.activeType == 'ECGData' || this.activeType == 'bodyData' || this.activeType == 'SleepDatas') {
this.$emit('back', 1)
} else {
this.$emit('back', 2)
}
},
getHours(minutes, type) {
if (type == 0) {
return Math.floor((minutes / 60).toFixed(2));
}
if (type == 1) {
var minutes = minutes % 60;
if (minutes < 10) {
minutes = '0' + minutes;
}
return minutes;
}
}
}
}
@ -284,6 +313,9 @@
width: 50rpx;
}
}
.data-icon {
margin-right: 20rpx;
}
.time {
font-weight: 300;
font-size: 24rpx;

View File

@ -1,7 +1,7 @@
<template>
<view>
<z-paging ref="paging"refresher-only @onRefresh="onRefresh">
<view class="flx jcsb ac">
<view class="flx jcsb ac" style="margin-bottom: 100rpx">
<view class="left">
<view class="content-header">
<view class="sha-dow"></view>
@ -98,27 +98,7 @@
<image src="../../static/icon/xuetang.png" mode="widthFix"></image>
</view>
</view>
<view class="content-item" @click="toPageCom('bloodOxygen')">
<view class="title">
{{getNameByKey('bloodOxygen')}}
</view>
<view class="time">
{{dataListsNew.bloodOxygen.data_msg? dataListsNew.bloodOxygen.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.bloodOxygen.data_msg? (dataListsNew.bloodOxygen.data_msg[0]) : '--'}}
</view>
<view class="f_right">
<text class="icon">%</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/xueyang.png" mode="widthFix"></image>
</view>
</view>
<!-- 血压 -->
<view class="content-item" @click="toPageCom('bloodPressure')">
<view class="title">
{{getNameByKey('bloodPressure')}}
@ -141,93 +121,7 @@
</view>
</view>
<view class="content-item" @click="toPageCom('bodyTemperature')">
<view class="title">
{{getNameByKey('bodyTemperature')}}
</view>
<view class="time">
{{dataListsNew.bodyTemperature.data_msg? dataListsNew.bodyTemperature.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.bodyTemperature.data_msg? (dataListsNew.bodyTemperature.data_msg) : '--'}}
</view>
<view class="f_right">
<text class="icon"></text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/wendu.png" mode="widthFix"></image>
</view>
</view>
<view class="content-item" @click="toPageCom('pulseReat')">
<view class="title">
{{getNameByKey('pulseReat')}}
</view>
<view class="time">
{{dataListsNew.pulseReat.data_msg? dataListsNew.pulseReat.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.pulseReat.data_msg? (dataListsNew.pulseReat.data_msg[0]) : '--'}}
</view>
<view class="f_right">
<text class="icon">/</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/mailv.png" mode="widthFix"></image>
</view>
</view>
<view class="content-item" @click="toPageCom('ECGData')">
<view class="title">
心电图
</view>
<view class="time">
{{dataListsNew.ECGData.data_msg? dataListsNew.ECGData.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.ECGData.data_msg? (dataListsNew.ECGData.data_msg.heartRate || dataListsNew.ECGData.data_msg.meanHeartRate) : '--'}}
</view>
<view class="f_right">
<text class="icon">/</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/xindiantu.png" style="width: 220rpx;" mode="widthFix"></image>
</view>
</view>
<view class="content-item" @click="toPageCom('bodyData')">
<view class="title">
身体成分
</view>
<view class="time">
{{dataListsNew.bodyData.data_msg? dataListsNew.bodyData.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.bodyData.data_msg? (dataListsNew.bodyData.data_msg.BMI ) : '--'}}
</view>
<view class="f_right">
<text class="icon">BMI</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/rtcf.png" style="width: 220rpx;" mode="widthFix"></image>
</view>
</view>
<!-- 尿酸 -->
<view class="content-item" @click="toPageCom('bloodLiquid')">
<view class="title">
尿酸
@ -250,6 +144,30 @@
</view>
</view>
<!-- 心率 -->
<view class="content-item" @click="toPageCom('pulseReat')">
<view class="title">
{{getNameByKey('pulseReat')}}
</view>
<view class="time">
{{dataListsNew.pulseReat.data_msg? dataListsNew.pulseReat.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.pulseReat.data_msg? (dataListsNew.pulseReat.data_msg[0]) : '--'}}
</view>
<view class="f_right">
<text class="icon">/</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/mailv.png" mode="widthFix"></image>
</view>
</view>
<!-- 血脂 -->
<view class="content-item" @click="toPageCom('bloodLiquidAll')">
<view class="title">
{{getNameByKey('bloodLiquidAll')}}
@ -296,6 +214,104 @@
</view>
</view>
</view>
<!-- 身体成分 -->
<view class="content-item">
<view @click="toPageCom('bodyData')">
<view class="title">
身体成分
</view>
<view class="time">
{{dataListsNew.bodyData.data_msg? dataListsNew.bodyData.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.bodyData.data_msg? (dataListsNew.bodyData.data_msg.BMI ) : '--'}}
</view>
<view class="f_right">
<text class="icon">BMI</text>
</view>
</view>
</view>
<view class="bg" style="bottom: 220rpx">
<image src="../../static/icon/rtcf.png" style="width: 220rpx;" mode="widthFix"></image>
</view>
</view>
<view @click="toPageCom('ECGData')">
<view class="title">
心电图
</view>
<view class="time">
{{dataListsNew.ECGData.data_msg? dataListsNew.ECGData.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.ECGData.data_msg? (dataListsNew.ECGData.data_msg.heartRate || dataListsNew.ECGData.data_msg.meanHeartRate) : '--'}}
</view>
<view class="f_right">
<text class="icon">/</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/xindiantu.png" style="width: 220rpx;" mode="widthFix"></image>
</view>
</view>
</view>
<!-- 心电图 -->
<!-- <view class="content-item" @click="toPageCom('ECGData')">
</view> -->
<!-- 血氧 -->
<view class="content-item" @click="toPageCom('bloodOxygen')">
<view class="title">
{{getNameByKey('bloodOxygen')}}
</view>
<view class="time">
{{dataListsNew.bloodOxygen.data_msg? dataListsNew.bloodOxygen.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.bloodOxygen.data_msg? (dataListsNew.bloodOxygen.data_msg[0]) : '--'}}
</view>
<view class="f_right">
<text class="icon">%</text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/xueyang.png" mode="widthFix"></image>
</view>
</view>
<!-- 体温 -->
<view class="content-item" @click="toPageCom('bodyTemperature')">
<view class="title">
{{getNameByKey('bodyTemperature')}}
</view>
<view class="time">
{{dataListsNew.bodyTemperature.data_msg? dataListsNew.bodyTemperature.device_real_time + '更新' : '--'}}
</view>
<view class="date">
<view class="flex_data">
<view class="f_left">
{{dataListsNew.bodyTemperature.data_msg? (dataListsNew.bodyTemperature.data_msg) : '--'}}
</view>
<view class="f_right">
<text class="icon"></text>
</view>
</view>
</view>
<view class="bg">
<image src="../../static/icon/wendu.png" mode="widthFix"></image>
</view>
</view>
</view>
</view>
</view>

View File

@ -0,0 +1,66 @@
<template>
<view>
<view class="spinner-inside" :style="{
width: size + 110 + 'px',
}">
<view :style="{ backgroundColor:color }" class="bounce1"></view>
<view :style="{ backgroundColor:color }" class="bounce2"></view>
<view :style="{ backgroundColor:color }" class="bounce3"></view>
</view>
</view>
</template>
<script>
export default {
name: 'bounce',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
text-align: center;
}
.spinner-inside > view {
width: 30px;
height: 30px;
border-radius: 100%;
display: inline-block;
-webkit-animation: bouncedelay 1.4s infinite ease-in-out;
animation: bouncedelay 1.4s infinite ease-in-out;
/* Prevent first frame from flickering when animation starts */
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.spinner-inside .bounce1 {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.spinner-inside .bounce2 {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
@-webkit-keyframes bouncedelay {
0%, 80%, 100% { -webkit-transform: scale(0.0) }
40% { -webkit-transform: scale(1.0) }
}
@keyframes bouncedelay {
0%, 80%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 40% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<view>
<view class="spinner-inside" :style="{
width: size+20+'px',
height: size+20+'px'
}">
<view :style="{ backgroundColor:color }" class="double-bounce1"></view>
<view :style="{ backgroundColor:color }" class="double-bounce2"></view>
</view>
</view>
</template>
<script>
export default {
name: 'doubleBounce',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
position: relative;
}
.double-bounce1, .double-bounce2 {
width: 100%;
height: 100%;
border-radius: 50%;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
-webkit-animation: bounce 2.0s infinite ease-in-out;
animation: bounce 2.0s infinite ease-in-out;
}
.double-bounce2 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
@-webkit-keyframes bounce {
0%, 100% { -webkit-transform: scale(0.0) }
50% { -webkit-transform: scale(1.0) }
}
@keyframes bounce {
0%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 50% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<view>
<view class="spinner-inside" :style="{
width: size+'px',
height: size+'px'
}">
<view :style="{ backgroundColor:color,width:size-10+'px',height:size-10+'px'}" class="cube1"></view>
<view :style="{ backgroundColor:color,width:size-10+'px',height:size-10+'px'}" class="cube2"></view>
</view>
</view>
</template>
<script>
export default {
name: 'doubleCube',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 50% auto;
position: relative;
transform: translate(-50%, -50%);
}
.cube1, .cube2 {
position: absolute;
top: 0;
left: 0;
-webkit-animation: cubemove 1.8s infinite ease-in-out;
animation: cubemove 1.8s infinite ease-in-out;
}
.cube2 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
@-webkit-keyframes cubemove {
25% { -webkit-transform: translateX(42px) rotate(-90deg) scale(0.5) }
50% { -webkit-transform: translateX(42px) translateY(42px) rotate(-180deg) }
75% { -webkit-transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5) }
100% { -webkit-transform: rotate(-360deg) }
}
@keyframes cubemove {
25% {
transform: translateX(42px) rotate(-90deg) scale(0.5);
-webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);
} 50% {
transform: translateX(42px) translateY(42px) rotate(-179deg);
-webkit-transform: translateX(42px) translateY(42px) rotate(-179deg);
} 50.1% {
transform: translateX(42px) translateY(42px) rotate(-180deg);
-webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
} 75% {
transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5);
-webkit-transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5);
} 100% {
transform: rotate(-360deg);
-webkit-transform: rotate(-360deg);
}
}
</style>

View File

@ -0,0 +1,70 @@
<template>
<view>
<view class="spinner-inside" :style="{
width: size+40+'px',
height: size+40+'px'
}">
<view :style="{ backgroundColor:color }" class="dot1"></view>
<view :style="{ backgroundColor:color }" class="dot2"></view>
</view>
</view>
</template>
<script>
export default {
name: 'doubleDot',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
position: relative;
text-align: center;
-webkit-animation: rotate 2.0s infinite linear;
animation: rotate 2.0s infinite linear;
}
.dot1, .dot2 {
width: 60%;
height: 60%;
display: inline-block;
position: absolute;
top: 0;
background-color: #67CF22;
border-radius: 100%;
-webkit-animation: bounce 2.0s infinite ease-in-out;
animation: bounce 2.0s infinite ease-in-out;
}
.dot2 {
top: auto;
bottom: 0px;
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
@-webkit-keyframes rotate { 100% { -webkit-transform: rotate(360deg) }}
@keyframes rotate { 100% { transform: rotate(360deg); -webkit-transform: rotate(360deg) }}
@-webkit-keyframes bounce {
0%, 100% { -webkit-transform: scale(0.0) }
50% { -webkit-transform: scale(1.0) }
}
@keyframes bounce {
0%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 50% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
</style>

View File

@ -0,0 +1,147 @@
<template>
<view>
<view class="spinner-inside" :style="{
width: size+'px',
height: size+'px'
}">
<view class="spinner-inside-container container1">
<view :style="{ backgroundColor:color }" class="circle1"></view>
<view :style="{ backgroundColor:color }" class="circle2"></view>
<view :style="{ backgroundColor:color }" class="circle3"></view>
<view :style="{ backgroundColor:color }" class="circle4"></view>
</view>
<view class="spinner-inside-container container2">
<view :style="{ backgroundColor:color }" class="circle1"></view>
<view :style="{ backgroundColor:color }" class="circle2"></view>
<view :style="{ backgroundColor:color }" class="circle3"></view>
<view :style="{ backgroundColor:color }" class="circle4"></view>
</view>
<view class="spinner-inside-container container3">
<view :style="{ backgroundColor:color }" class="circle1"></view>
<view :style="{ backgroundColor:color }" class="circle2"></view>
<view :style="{ backgroundColor:color }" class="circle3"></view>
<view :style="{ backgroundColor:color }" class="circle4"></view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'loop',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
position: relative;
}
.container1 > view, .container2 > view, .container3 > view {
width: 12px;
height: 12px;
border-radius: 100%;
position: absolute;
-webkit-animation: bouncedelay 1.2s infinite ease-in-out;
animation: bouncedelay 1.2s infinite ease-in-out;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.spinner-inside .spinner-inside-container {
position: absolute;
width: 100%;
height: 100%;
}
.container2 {
-webkit-transform: rotateZ(45deg);
transform: rotateZ(45deg);
}
.container3 {
-webkit-transform: rotateZ(90deg);
transform: rotateZ(90deg);
}
.circle1 { top: 0; left: 0; }
.circle2 { top: 0; right: 0; }
.circle3 { right: 0; bottom: 0; }
.circle4 { left: 0; bottom: 0; }
.container2 .circle1 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.container3 .circle1 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.container1 .circle2 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.container2 .circle2 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
.container3 .circle2 {
-webkit-animation-delay: -0.7s;
animation-delay: -0.7s;
}
.container1 .circle3 {
-webkit-animation-delay: -0.6s;
animation-delay: -0.6s;
}
.container2 .circle3 {
-webkit-animation-delay: -0.5s;
animation-delay: -0.5s;
}
.container3 .circle3 {
-webkit-animation-delay: -0.4s;
animation-delay: -0.4s;
}
.container1 .circle4 {
-webkit-animation-delay: -0.3s;
animation-delay: -0.3s;
}
.container2 .circle4 {
-webkit-animation-delay: -0.2s;
animation-delay: -0.2s;
}
.container3 .circle4 {
-webkit-animation-delay: -0.1s;
animation-delay: -0.1s;
}
@-webkit-keyframes bouncedelay {
0%, 80%, 100% { -webkit-transform: scale(0.0) }
40% { -webkit-transform: scale(1.0) }
}
@keyframes bouncedelay {
0%, 80%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 40% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
</style>

View File

@ -0,0 +1,46 @@
<template>
<view>
<view :style="{
backgroundColor: color,
width: size+20+'px',
height: size+20+'px' }" class="spinner-inside"></view>
</view>
</template>
<script>
export default {
name: 'rotatePlane',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
-webkit-animation: rotateplane 1.2s infinite ease-in-out;
animation: rotateplane 1.2s infinite ease-in-out;
}
@-webkit-keyframes rotateplane {
0% { -webkit-transform: perspective(120px) }
50% { -webkit-transform: perspective(120px) rotateY(180deg) }
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) }
}
@keyframes rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
} 50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
} 100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
</style>

View File

@ -0,0 +1,47 @@
<template>
<view>
<view :style="{
backgroundColor: color,
width: size+40+'px',
height: size+40+'px' }" class="spinner-inside"></view>
</view>
</template>
<script>
export default {
name: 'scaleOut',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
border-radius: 100%;
-webkit-animation: scaleout 1.0s infinite ease-in-out;
animation: scaleout 1.0s infinite ease-in-out;
}
@-webkit-keyframes scaleout {
0% { -webkit-transform: scale(0.0) }
100% {
-webkit-transform: scale(1.0);
opacity: 0;
}
}
@keyframes scaleout {
0% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 100% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
opacity: 0;
}
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<view>
<view class="spinner-inside" :style="{
width: size+20+'px',
height: size+20+'px'
}">
<view :style="{ backgroundColor:color }" class="rect1"></view>
<view :style="{ backgroundColor:color }" class="rect2"></view>
<view :style="{ backgroundColor:color }" class="rect3"></view>
<view :style="{ backgroundColor:color }" class="rect4"></view>
<view :style="{ backgroundColor:color }" class="rect5"></view>
</view>
</view>
</template>
<script>
export default {
name: 'shrinkRect',
props: {
color: String,
size: Number
}
}
</script>
<style scoped>
.spinner-inside {
margin: 25px auto;
text-align: center;
font-size: 10px;
}
.spinner-inside > view {
height: 100%;
width: 12%;
margin: 0 2px;
display: inline-block;
-webkit-animation: stretchdelay 1.2s infinite ease-in-out;
animation: stretchdelay 1.2s infinite ease-in-out;
}
.spinner-inside .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner-inside .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner-inside .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner-inside .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
@-webkit-keyframes stretchdelay {
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
@keyframes stretchdelay {
0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
} 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<!-- #ifdef H5 -->
<transition name="fade">
<!-- #endif -->
<view class="mask" v-show="isActive" :class="{ 'full-screen': isFullScreen }" :style="{ backgroundColor }">
<view class="spinner" :style="{ transform:`translate(-50%, -${translateY}%)`}">
<slot>
<!-- ==========在这里改成选择的那一个========== -->
<shrinkRect :color="color" :size="size" />
<!-- ==========在这里改成选择的那一个========== -->
</slot>
<view v-if="text.length" :style="{ color:textColor }">
{{ text }}
</view>
</view>
</view>
<!-- #ifdef H5 -->
</transition>
<!-- #endif -->
</template>
<script>
// ====================
// import loop from './loaders/loop.vue'
// import bounce from './loaders/bounce.vue'
// import doubleBounce from './loaders/double-bounce.vue'
// import doubleCube from './loaders/double-cube.vue'
// import doubleDot from './loaders/double-dot.vue'
// import rotatePlane from './loaders/rotate-plane.vue'
// import scaleOut from './loaders/scale-out.vue'
import shrinkRect from './loaders/shrink-rect.vue'
// ====================
export default {
name: 'ourLoading',
components: {
// ====================
// loop,
// bounce,
// doubleBounce,
// doubleCube,
// doubleDot,
// rotatePlane,
// scaleOut,
shrinkRect
// ====================
},
props: {
active: Boolean,
translateY: {
type: Number,
default: 50
},
text: {
type: String,
default: ''
},
color: {
type: String,
default: '#06193a'
},
textColor: {
type: String,
default: '#06193a'
},
isFullScreen: {
type: Boolean,
default: false
},
backgroundColor: {
type: String,
default: 'rgba(255, 255, 255, .9)'
},
size: {
type: Number,
default: 60
}
},
data() {
return {
isActive: this.active || false
}
},
watch: {
active(value) {
this.isActive = value
}
}
}
</script>
<style scoped>
.mask {
position: absolute;
width: 60%;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 90;
transition: opacity .3s linear;
}
.full-screen {
position: fixed;
width: 60%;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.spinner {
position: absolute;
top: 50%;
left: 50%;
text-align: center;
}
/* #ifdef H5 */
.fade-enter-active,
.fade-leave-active {
transition: opacity .3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
/* #endif */
</style>

View File

@ -1,6 +1,11 @@
<template>
<view>
<tm-nav-bar left-icon="arrow-left" title="睡眠" @clickLeft="back" :rbgs="false"/>
<tm-nav-bar
left-icon="arrow-left"
title="睡眠"
@clickLeft="back"
:rightText="`全部数据`"
@clickRight="goAllPath" />
<view class="flx jcsb ac" style="height: 40rpx;background-color: #fff;padding: 20rpx;">
<view class="" style="font-size: 40rpx;font-weight: bold;">
@ -261,6 +266,11 @@
this.$emit('back', 1)
},
//
goAllPath() {
this.$emit('allData', 3)
},
getDataList(){
let type = 'SleepDatas'
let res = this.$store.dispatch('api/getDeviceListDays', {

View File

@ -12,7 +12,7 @@ export default () => {
config.baseURL = readBaseUrl; // 测试地址
}
// #ifdef APP-PLUS
// #ifdef APP-PLUS
config.baseURL = baseUrl; // 测试地址
// #endif
return config
@ -41,10 +41,10 @@ export default () => {
let ob = (config.method == 'GET'? config.params : config.data)
const custom = config.custom.hideLoading || false
if(!custom){
uni.showLoading({
mask: true,
title:"加载中..."
});
// uni.showLoading({
// mask: true,
// title:"加载中..."
// });
}
return config
@ -54,6 +54,7 @@ export default () => {
// 响应拦截
uni.$u.http.interceptors.response.use((response) => {
console.log(response)
uni.hideLoading({});
@ -113,7 +114,7 @@ export default () => {
}, (response) => {
uni.showToast({
mask: true,
title: '服务器响应失败' + response.statusCode,
title: '网络断开',
icon: 'none'
})
return Promise.reject(response)

View File

@ -12,6 +12,9 @@
<script src="./js/voice.js"></script>
<script src="./js/crypto-js.min.js"></script>
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
<!-- 文字转拼音 -->
<script src="./js/pinyin.js"></script>
<script src="js/w_md5.js"></script>
<!-- 构建界面 -->
@ -27,8 +30,11 @@
<!-- 视频 -->
<div class="video-wrap">
<div id="shadow">
<div id="shadow-text">模型正在启动……</div>
</div>
<video id="myVideo" muted loop autoplay playsinline>
<source src="https://img.agrimedia.cn/bmsc/%E9%A3%9E%E4%B9%A620240918-175041.mp4" type="video/mp4">
<source src="./demo/ple.mp4" type="video/mp4">
</video>
</div>
<audio
@ -84,6 +90,8 @@
var Question = '';
var Subtitles = '';
let { pinyin } = pinyinPro;
function getURLParameter(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
@ -124,7 +132,7 @@
dataLines.push(line.trim());
}
});
const dataJson = dataLines.join('');
try {
if (dataJson) {
@ -137,7 +145,7 @@
console.error('解析 data 字段为 JSON 时出错:', error);
}
});
// 如果没有找到 finish_reason 为 "stop" 的事件,则返回 null 或其他默认值
return stopEvent;
}
@ -146,17 +154,17 @@
<!-- 讯飞语音识别 -->
<script>
window.onload = function () {
reset();
};
function reset() {
var videoElement = document.getElementById('myVideo');
var startTime = 5; // 开始时间(以秒为单位)
var endTime = 10; // 结束时间(以秒为单位)
var timeUpdateListener; // 保存timeupdate事件的监听器
// 遮罩视频
var shadowDom = document.getElementById('shadow');
var shadowText = document.getElementById('shadow-text');
// 指定段落
function playVideoSegment(startTime, endTime) {
function playVideoSegment(startTime, endTime) {
videoElement.currentTime = startTime;
setTimeout(() => {
videoElement.play();
@ -196,7 +204,7 @@
var audioElement = document.getElementById('myAudio');
var isPlaying = false; // 是否播放
audioElement.muted = true; // 先静音
// 获取页面元素
var element = document.getElementById("elementId");
@ -210,8 +218,7 @@
endRec.style.display = "none";
stopRec.style.display = "none";
var token = null;
let times = null;
@ -219,6 +226,16 @@
var user = userInfo(JSON.parse(getURLParameter('user')));
var apitoken = getURLParameter('token');
var deviceId = getURLParameter('deviceId');
var loading = getURLParameter('loading');
setTimeout(() => {
if (loading) {
shadowDom.style.display = 'none';
} else {
alert('异常')
shadowText.innerHTML = '环境异常,请检查网络'
}
}, 500);
// 获取微软token
@ -247,7 +264,7 @@
for (let i = 0; i < exampleData.length; i++) {
exampleData[i].name = demoData[exampleData[i].type]
};
// 过滤掉非对象类型的值
const filteredData = Object.entries(exampleData).filter(([key, value]) => typeof value === 'object');
@ -260,77 +277,81 @@
/*
* 实例化迅飞语音听写流式版WebAPI
*/
var seconds = 10;
var seconds = 5;
var gaptime = null;
const voice = new Voice({
var voice = new Voice({
// 服务接口认证信息
appId: '5f4ffdeb',
apiSecret: 'OGIwM2RlMjBkOTI5Mzk5YTJlMzUwODI5',
apiKey: '0b17a761b6b7174b789f639119d7e29a',
onWillStatusChange: function (oldStatus, newStatus) {
console.log(oldStatus, newStatus, '交互逻辑')
},
onWillStatusChange: function (oldStatus, newStatus) {},
onTextChange: function (text) {
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
// 2秒钟内没有说话就自动关闭
// 如果已有定时器在运行,则清除它
if (gaptime) {
clearInterval(gaptime);
};
gaptime = null;
};
// 重置倒计时
seconds = 10;
console.log(text)
seconds = 5;
gaptime = setInterval(() => {
console.log(seconds, '倒计时')
seconds--;
if (voiceTxt.innerText) {
console.log('有 text 参数'); // 如果有 text 参数,打印 1
if (text) {
clearInterval(gaptime);
gaptime = null;
seconds = 5;
// 3秒钟内没有说话,就自动关闭
// 2秒钟内没有说话,就自动关闭
if (text) {
statusTxt.value = '正在听…';
if (!isCallbackExecuted) {
clearTimeout(times);
times = setTimeout(() => {
this.stop();
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
statusTxt.value = '正在听…';
console.log(new Date().getTime(), '收到文字')
const params = { msg: text };
// 判断关键字是否存在
const result = parseHealthQuery(params.msg);
console.log(JSON.stringify(result), '判断关键字是否存在')
isCallbackExecuted = true;
if (result) {
DetailDay(result.dataKey, result.date).then(res => {
let TargetData = res.data.data;
let TargetData = res.data.data;
if (result.dataKey == 'ECGData') {
TargetData.map(item => {
delete item.data_msg.wavefrom;
delete item.data_msg.list;
})
}
if (result.dataKey == 'bloodLiquid') {
let uricAcidVal = [];
let lowDensity = [];
let triacylglycerol = [];
let highDensity = [];
let cholesterol = [];
TargetData.map(item => {
item.data_msg.cholesterol = item.data_msg.cholesterol/100;
item.data_msg.highDensity = item.data_msg.highDensity/100;
item.data_msg.triacylglycerol = item.data_msg.triacylglycerol/100;
item.data_msg.uricAcidVal = item.data_msg.uricAcidVal/10000;
item.data_msg.lowDensity = item.data_msg.lowDensity/100;
item.data_msg.cholesterol = cholesterol.push((item.data_msg.cholesterol/100).toFixed(2));
item.data_msg.highDensity = highDensity.push((item.data_msg.highDensity/100).toFixed(2));
item.data_msg.triacylglycerol = triacylglycerol.push((item.data_msg.triacylglycerol/100).toFixed(2));
item.data_msg.uricAcidVal = uricAcidVal.push((item.data_msg.uricAcidVal/10).toFixed(2));
item.data_msg.lowDensity = lowDensity.push((item.data_msg.lowDensity/100).toFixed(2));
})
TargetData = '尿酸: ' + JSON.stringify(uricAcidVal) + ',高密度脂蛋白: ' + JSON.stringify(highDensity) + ',低密度脂蛋白: ' + JSON.stringify(lowDensity) + ',甘油三脂: ' + JSON.stringify(triacylglycerol) + ',总胆固醇: ' + JSON.stringify(cholesterol);
}
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。`
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。提示:回答尿酸时单位转换成“微摩尔/升”`
console.log(Question, '问题=========================问题');
/*
* 调用接口 传递关键信息 文字转语音
*/
@ -381,7 +402,7 @@
xhr.onerror = function () {
console.error('An error occurred during the transaction', xhr.statusText);
};
/*
* 关键字转换
*/
@ -471,11 +492,13 @@
isCallbackExecuted = true;
return;
}
}, 3000);
}, 2000);
}
}
} else if (seconds == 0){
reset();
clearInterval(gaptime);
closeShibie();
return;
}
}, 1000);
}
@ -490,6 +513,11 @@
// 关闭识别
endRec.addEventListener("click", function() {
closeShibie();
// 直接开始
setTimeout(() => {
startShibie();
}, 100);
});
// 暂停识别
@ -500,25 +528,26 @@
function stopPlay() {
/**暂停播放**/
if (audioElement.paused) {
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
} else {
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
}
};
function startShibie() {
/**开始识别**/
statusTxt.value = '正在听…';
voiceTxt.innerText = '';
stopRec.textContent = '暂停';
@ -526,14 +555,8 @@
// 先静音即可处理解决(提前做交互)
audioElement.muted = false;
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
seconds = 10;
audioElement.currentTime = 0;
audioElement.pause();
voice.start();
@ -544,28 +567,18 @@
}
function closeShibie() {
reset();
/**关闭识别**/
voiceTxt.innerText = '';
statusTxt.value = '';
stopRec.textContent = '暂停';
voice.stop();
// 音频
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
// 视频
audioElement.pause();
audioElement.currentTime = 0;
// 视频
replayVideoSegment(0, 60);
isCallbackExecuted = false;
seconds = 10;
voice.stop();
console.log('关闭识别');
startRec.style.display = 'block';
endRec.style.display = 'none';
@ -577,7 +590,7 @@
function showModal() {
modal.style.display = 'block';
dialog.style.display = 'block';
}
}
// 隐藏弹窗和遮罩
function hideModal() {
@ -638,7 +651,7 @@
startRec.style.display = "none";
endRec.style.display = "block";
stopRec.style.display = "block";
voiceTxt.innerText = '';
NextPlayVideo(response, filterString(Subtitles, ['*', ' ']));
}).catch(e => {
hideModal();
@ -664,43 +677,23 @@
// 播放音频
audioElement.play();
console.log(new Date().getTime(), '播放音频')
// 循环视频
replayVideoSegment(60, 120);
// 监听播放技术
myAudio.addEventListener('ended', function() {
console.log('音频播放已结束!');
// 停止倒计时
startRec.style.display = 'block';
endRec.style.display = 'none';
stopRec.style.display = 'none';
statusTxt.value = '';
voiceTxt.innerText = '';
replayVideoSegment(0, 60);
hideModal()
// 播放结束重新开始监听
replayVideoSegment(0, 60);
voice.stop();
startShibie();
});
Subtitles = "";
}
// 防抖
function throttle(fn, wait) {
let lastTime = 0; // 上一次调用的时间
return function (...args) {
const now = Date.now(); // 当前时间
// 如果距离上次调用已经超过设定时间,则调用函数
if (now - lastTime > wait) {
lastTime = now; // 更新上一次调用的时间
fn.apply(this, args); // 以正确的`this`和参数调用函数
}
};
}
// 拿到的数据移除*
function filterString(str, charsToRemove) {
// 这里的正则表达式是通过将charsToRemove数组中的字符转换为字符类character class来构建的
@ -723,15 +716,15 @@
demoData = {
bloodGlucose: "血糖",
SleepDatas: "睡眠",
bloodOxygen: "血氧",
bloodOxygen: ['血氧', '血氧饱和度'],
bloodPressure: '血压',
meiTuo: '梅脱',
pulseReat: '心率',
bodyTemperature: '体温',
ECGData: '心电图',
bloodLiquid: ['血脂', '血液', '尿酸'],
bloodLiquid: ['血脂', '血液', '尿酸', '胆固醇', '甘油三脂', '高密度脂蛋白', '低密度脂蛋白'],
bodyData: '身体成分',
stepIndex: ['运动', '步数']
stepIndex: ['运动', '步数']
};
}
@ -742,16 +735,22 @@
const day = today.getDate();
// 初始化日期为今天
let targetDate = new Date(year, month, day);
let targetDate = new Date(year, month - 1, day);
// 检查时间词并设置目标日期
if (query.includes("昨天")) {
targetDate.setDate(day - 1);
} else if (query.includes("前天")) {
targetDate.setDate(day - 2);
}
const formattedDate = `${targetDate.getFullYear()}-${('0' + targetDate.getMonth()).slice(-2)}-${('0' + targetDate.getDate()).slice(-2)}`;
let offsetDays = 0; // 用于存储需要偏移的天数
if (query.includes("昨天")) {
offsetDays = -1;
} else if (query.includes("前天")) {
offsetDays = -2;
}
// 应用天数偏移,并正确处理跨月或跨年情况
targetDate.setDate(targetDate.getDate() + offsetDays);
// 格式化日期,确保月份和日期都是两位数
const formattedDate = `${targetDate.getFullYear()}-${String(targetDate.getMonth() + 1).padStart(2, '0')}-${String(targetDate.getDate()).padStart(2, '0')}`;
// 创建一个辅助函数来检查 bloodLiquid 对象是否包含查询字符串
function isBloodLiquidMatch(bloodLiquidData, query) {
@ -760,7 +759,7 @@
// 在查询逻辑中使用这个辅助函数
for (let key in demoData) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' ) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' || typeof demoData[key] === 'object' && key === 'bloodOxygen' ) {
if (isBloodLiquidMatch(demoData[key], query)) {
key === 'stepIndex'? key = 'step_split' : ''; // 修改步数参数
return {
@ -773,13 +772,18 @@
dataKey: key,
date: formattedDate
};
}
} else if (pinyin(query, { toneType: 'none' }).replace(/\s/g, '').includes("xueyang")) { // 不容易识别转拼音,上面其实都可以优化
return {
dataKey: 'bloodOxygen',
date: formattedDate
};
}
}
// 如果没有找到匹配的数据项则返回null或错误信息这里选择返回null
return null;
}
}
};
</script>
@ -812,6 +816,30 @@
border-radius: 10px;
}
#shadow {
position: fixed;
z-index: 99999;
width: 100%;
height: 100vh;
left: 0;
top: 0;
background-color: #06193a;
}
#shadow-text {
width: 100%;
height: 100vh;
position: absolute;
text-align: center;
line-height: 100vh;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0 auto;
color: #fff;
}
#myVideo {
width: 100%;
height: 100% !important;

BIN
hybrid/html/demo/ple.mp4 Normal file

Binary file not shown.

1
hybrid/html/js/pinyin.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -110,6 +110,7 @@
};
// 连接WebSocket
connectWebSocket() {
console.log('连接WebSocket')
return this.getWebSocketUrl().then(url => {
let iatWS;
if ('WebSocket' in window) {
@ -122,8 +123,11 @@
}
this.webSocket = iatWS;
this.setStatus('init');
iatWS.onopen = e => {
this.setStatus('ing');
console.log('ws开启重新开始录音');
// 重新开始录音
setTimeout(() => {
this.webSocketSend();
@ -140,6 +144,18 @@
};
})
};
// 防抖函数
debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
// 初始化浏览器录音
recorderInit() {
// 创建音频环境
@ -216,9 +232,10 @@
};
// 向webSocket发送数据(音频二进制数据经过Base64处理)
webSocketSend() {
console.log('发送数据')
if (this.webSocket.readyState !== 1) return false;
// 音频数据
const audioData = this.audioData.splice(0, 1280);
let audioData = this.audioData.splice(0, 1280);
const params = {
common: {
app_id: this.appId,
@ -237,14 +254,17 @@
audio: this.toBase64(audioData)
}
};
console.log(params, 'socket数据');
// 发送数据
this.webSocket.send(JSON.stringify(params));
this.handlerInterval = setInterval(() => {
// websocket未连接
if (this.webSocket.readyState !== 1) {
this.audioData = [];
clearInterval(this.handlerInterval);
return false;
return false;
};
if (this.audioData.length === 0) {
if (this.status === 'end') {
@ -312,9 +332,10 @@
this.webSocket.close();
}
};
// 启动录音
recorderStart() {
if (!this.audioContext) {
if (!this.audioContext) {
this.recorderInit();
} else {
this.audioContext.resume();
@ -340,8 +361,10 @@
this.setResultText({ resultText: '', resultTextTemp: '' });
};
// 停止
stop() {
stop() {
console.log('停了停了停了停了停了停了停了停了停了停了');
this.recorderStop();
this.webSocket.close();
};
};
}));

View File

@ -7,6 +7,9 @@ import uView from '@/uni_modules/uview-ui'
import store from '@/store'
import request from '@/config/request.js'
import ourLoading from '@/components/our-loading/our-loading.vue'
Vue.component('ourLoading', ourLoading)
Vue.use(uView)
Vue.use(request)

View File

@ -2,14 +2,18 @@
"name" : "中鼎云医",
"appid" : "__UNI__24DA8DD",
"description" : "中鼎云医",
"versionName" : "1.2.5",
"versionCode" : 125,
"versionName" : "1.2.8",
"versionCode" : 128,
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"compatible" : {
// trueHBuilderX1.9.0
"ignoreVersion" : true
},
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
@ -23,8 +27,6 @@
},
/* */
"distribute" : {
/* android */
"screenOrientation" : "portrait", // "landscape"
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
@ -45,7 +47,6 @@
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"
]
},
// "orientation": "portrait",
/* ios */
"ios" : {
"dSYMs" : false

BIN
node_modules/.DS_Store generated vendored Normal file

Binary file not shown.

132
node_modules/.vue-global-types/vue_3.3_false.d.ts generated vendored Normal file
View File

@ -0,0 +1,132 @@
// @ts-nocheck
export {};
; declare module 'vue' {
export interface GlobalComponents { }
export interface GlobalDirectives { }
}
; declare global {
const __VLS_intrinsicElements: __VLS_IntrinsicElements;
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
const __VLS_unref: typeof import('vue').unref;
const __VLS_placeholder: any;
const __VLS_nativeElements = {
...{} as SVGElementTagNameMap,
...{} as HTMLElementTagNameMap,
};
type __VLS_IntrinsicElements = import('vue/jsx-runtime').JSX.IntrinsicElements;
type __VLS_Element = import('vue/jsx-runtime').JSX.Element;
type __VLS_GlobalComponents = import('vue').GlobalComponents & Pick<typeof import('vue'), 'Transition' | 'TransitionGroup' | 'KeepAlive' | 'Suspense' | 'Teleport'>;
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
type __VLS_unknownDirective = (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
type __VLS_WithComponent<N0 extends string, LocalComponents, N1 extends string, N2 extends string, N3 extends string> =
N1 extends keyof LocalComponents ? N1 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? N2 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? N3 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N3] } :
N1 extends keyof __VLS_GlobalComponents ? N1 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N1] } :
N2 extends keyof __VLS_GlobalComponents ? N2 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N2] } :
N3 extends keyof __VLS_GlobalComponents ? N3 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N3] } :
{ [K in N0]: unknown };
type __VLS_FunctionalComponentProps<T, K> =
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
: T extends (props: infer P, ...args: any) => any ? P :
{};
type __VLS_IsFunction<T, K> = K extends keyof T
? __VLS_IsAny<T[K]> extends false
? unknown extends T[K]
? false
: true
: false
: false;
type __VLS_NormalizeComponentEvent<Props, Events, onEvent extends keyof Props, Event extends keyof Events, CamelizedEvent extends keyof Events> = (
__VLS_IsFunction<Props, onEvent> extends true
? Props
: __VLS_IsFunction<Events, Event> extends true
? { [K in onEvent]?: Events[Event] }
: __VLS_IsFunction<Events, CamelizedEvent> extends true
? { [K in onEvent]?: Events[CamelizedEvent] }
: Props
) & Record<string, unknown>;
// fix https://github.com/vuejs/language-tools/issues/926
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
? U extends T
? never
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
: never;
type __VLS_OverloadUnion<T> = Exclude<
__VLS_OverloadUnionInner<(() => never) & T>,
T extends () => never ? never : () => never
>;
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
? F extends (event: infer E, ...args: infer A) => any
? { [K in E & string]: (...args: A) => void; }
: never
: never;
type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
__VLS_UnionToIntersection<
__VLS_ConstructorOverloads<T> & {
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
}
>
>;
type __VLS_PrettifyGlobal<T> = { [K in keyof T]: T[K]; } & {};
type __VLS_PickFunctionalComponentCtx<T, K> = NonNullable<__VLS_PickNotAny<
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>>;
type __VLS_UseTemplateRef<T> = Readonly<import('vue').ShallowRef<T | null>>;
function __VLS_getVForSourceType(source: number): [number, number, number][];
function __VLS_getVForSourceType(source: string): [string, number, number][];
function __VLS_getVForSourceType<T extends any[]>(source: T): [
item: T[number],
key: number,
index: number,
][];
function __VLS_getVForSourceType<T extends { [Symbol.iterator](): Iterator<any> }>(source: T): [
item: T extends { [Symbol.iterator](): Iterator<infer T1> } ? T1 : never,
key: number,
index: undefined,
][];
// #3845
function __VLS_getVForSourceType<T extends number | { [Symbol.iterator](): Iterator<any> }>(source: T): [
item: number | (Exclude<T, number> extends { [Symbol.iterator](): Iterator<infer T1> } ? T1 : never),
key: number,
index: undefined,
][];
function __VLS_getVForSourceType<T>(source: T): [
item: T[keyof T],
key: keyof T,
index: number,
][];
// @ts-ignore
function __VLS_getSlotParams<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>;
// @ts-ignore
function __VLS_getSlotParam<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>[0];
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
: T extends (...args: any) => any
? T
: __VLS_unknownDirective;
function __VLS_withScope<T, K>(ctx: T, scope: K): ctx is T & K;
function __VLS_makeOptional<T>(t: T): { [K in keyof T]?: T[K] };
function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
T extends new (...args: any) => any
? (props: (K extends { $props: infer Props } ? Props : any) & Record<string, unknown>, ctx?: any) => __VLS_Element & { __ctx?: {
attrs?: any,
slots?: K extends { $slots: infer Slots } ? Slots : any,
emit?: K extends { $emit: infer Emit } ? Emit : any
} & { props?: (K extends { $props: infer Props } ? Props : any) & Record<string, unknown>; expose?(exposed: K): void; } }
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
: T extends (...args: any) => any ? T
: (_: {} & Record<string, unknown>, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: {} & Record<string, unknown> } };
function __VLS_elementAsFunction<T>(tag: T, endTag?: T): (_: T & Record<string, unknown>) => void;
function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): 2 extends Parameters<T>['length'] ? [any] : [];
function __VLS_normalizeSlot<S>(s: S): S extends () => infer R ? (props: {}) => R : S;
function __VLS_tryAsConstant<const T>(t: T): T;
}

View File

@ -1,5 +1,9 @@
{
"pages": [ //pages,
{
"path": "pages/index/blank",
"style": {}
},
{
"path": "pages/index/index",
"style": {}
@ -92,12 +96,11 @@
// "selectedIconPath": "static/logo.png"
// }]
// },
"globalStyle": {
"navigationBarTextStyle": "black",
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "中鼎云医",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationStyle": "custom",
"pageOrientation":"portrait"
"navigationStyle": "custom"
}
}

BIN
pages/.DS_Store vendored Normal file

Binary file not shown.

25
pages/index/blank.vue Normal file
View File

@ -0,0 +1,25 @@
<!-- 这个页面可以解决屏幕初始化问题 -->
<template>
<view class="main"></view>
</template>
<script>
export default {
onShow() {
setTimeout(() => {
uni.redirectTo({
url: '/pages/index/index'
})
}, 100);
}
}
</script>
<style scoped>
.main {
width: 100%;
height: 100vh;
background-color: #fff;
}
</style>

View File

@ -1,19 +1,8 @@
<template>
<view>
<view class="skeleton flx" v-if="loading">
<view style="width: 60%">
<x-skeleton type="banner" :loading="loading"></x-skeleton>
<x-skeleton type="banner" :loading="loading"></x-skeleton>
<x-skeleton type="banner" :loading="loading"></x-skeleton>
<x-skeleton type="banner" :loading="loading"></x-skeleton>
<x-skeleton type="banner" :loading="loading"></x-skeleton>
</view>
<view style="width: 40%">
<x-skeleton :loading="loading" :configs="customConfigs" fadeOut></x-skeleton>
</view>
</view>
<view class="content">
<ourLoading isFullScreen :active="loading" text="" textColor="#06193a"/>
<!-- 首页数据 -->
<view class="content-wrap" v-if="Sindex == 1">
<homeData :dataListsNew="dataListsNew" :deviceList="deviceList" :Activedevice="Activedevice" @deviceGet="deviceGet" @pageDetail="pageDetail"></homeData>
@ -24,17 +13,16 @@
<echartsData :pageData="pageData" @back="back" @allData="allData"></echartsData>
</view>
<!-- 日期筛选 全部数据 -->
<!-- 日期筛选全部数据 -->
<view class="content-wrap" v-if="Sindex == 3">
<allData @back="back" :activeType="activeType"></allData>
</view>
<!-- 睡眠 -->
<view class="content-wrap" v-if="Sindex == 4">
<sleep-info ref="sleep" @back="back"></sleep-info>
<sleep-info ref="sleep" @back="back" @allData="allData"></sleep-info>
</view>
<!-- 数字人webview原生页面 -->
<view class="right">
<web-view :src="urlLink"></web-view>
@ -85,6 +73,8 @@
SleepDatas:{}
},
loading: true,
name: '',
name1: '',
name2: '',
@ -98,7 +88,6 @@
type: ''
},
loading: true,
customConfigs: {
padding: '30rpx', //
gridRows: 2, //
@ -109,23 +98,33 @@
headBorderRadius: '12rpx', //head
}
}
},
},
onShow() {
this.onRefresh();
//
uni.onNetworkStatusChange((res) => {
console.log('111111')
});
},
onLoad() {
/*
* 首页数据
*/
this.onRefresh();
// #ifdef APP-PLUS
setTimeout(() => {
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
avaudio.requestRecordPermission(()=>{
console.log('申请麦克风权限');
avaudio.requestRecordPermission(() => {
console.log('申请麦克风权限');
});
}, 1000);
// #endif
this.urlLink = `/hybrid/html/ai.html`;
this.urlLink = `/hybrid/html/ai.html?loading=false`;
},
computed: {
...mapGetters({
@ -159,10 +158,18 @@
methods: {
getArrMaxValue,
onRefresh(pageNo, pageSize) {
onRefresh() {
//
this.$store.dispatch('api/getBindUserDeviceId').then(res => {
this.deviceList = res;
if (this.deviceList.length == 0) {
uni.showToast({
mask: true,
title: '账号未绑定手表设备,请移至小程序同步手表绑定。',
icon: 'none',
duration: 10000
})
}
//
if (!this.getActiceDevice.device_id) {
@ -213,8 +220,11 @@
delete this.dataListsNew.ECGData.data_msg.list;
}
this.urlLink = `/hybrid/html/ai.html?data=${JSON.stringify(this.dataListsNew)}&user=${JSON.stringify(this.getUserInfo)}&token=${store.getters['api/getApiToken']}&deviceId=${this.getActiceDevice.device_id}`;
this.loading = false;
setTimeout(() => {
this.loading = false;
}, 1000);
this.urlLink = `/hybrid/html/ai.html?data=${JSON.stringify(this.dataListsNew)}&user=${JSON.stringify(this.getUserInfo)}&token=${store.getters['api/getApiToken']}&deviceId=${this.getActiceDevice.device_id}&loading=${this.loading}`;
}
);
},
@ -234,6 +244,7 @@
return
} else if (str == 'SleepDatas') {
this.Sindex = 4;
this.activeType = str;
} else {
this.Sindex = 2;
this.activeType = str;
@ -288,6 +299,7 @@
},
allData(index) {
console.log(index)
this.Sindex = index;
},
@ -341,6 +353,7 @@
box-sizing: border-box;
overflow: hidden;
border-radius: 30rpx;
z-index: -1;
}
.content-header {
margin-bottom: 30rpx;

View File

@ -42,7 +42,6 @@
<view class="circle" style="background-color:#e933dd ;">
</view>
</view>
</view>
</view>
</view>

View File

@ -1,7 +1,7 @@
<template>
<view>
<!-- 返回 -->
<tm-nav-bar left-icon="arrow-left" title="登陆账号" :rbgs="false" :width="`100%`"/>
<tm-nav-bar left-icon="arrow-left" title="登陆账号" :rbgs="false" :width="`100%`" leftIcon=''/>
<view class="login flx flx_jc">
<view class="flx flx_jc flx_ac" style="width:100%; height: 100vh;">
<view class="content" style="height: 50vh">

BIN
static/.DS_Store vendored Normal file

Binary file not shown.

BIN
uni_modules/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -6,7 +6,7 @@
<!-- 背景图 -->
<img class="tm-navbar__header-bg" v-if="backgroundType" :src="backgroundImgUrl" alt="">
<!-- 左侧图标按钮 -->
<view @tap="onClickLeft" class="tm-navbar__header-btns tm-navbar__header-btns-left">
<view @tap="onClickLeft" class="tm-navbar__header-btns tm-navbar__header-btns-left" :style="leftIcon.length? 'background-color: #000' : 'background-color: transparent'">
<uni-icons v-if="leftIcon.length" :color="leftColor" :type="leftIcon" :size="iconSize" />
<text class="tm-navbar-btn-text" v-if="leftText.length"
:style="{ color: leftColor, fontSize: fontSize + 'px' }">{{ leftText }}</text>

BIN
unpackage/.DS_Store vendored

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
https://app.liuyingyong.cn/build/download/fcde2160-77e5-11ef-88bd-653596bd7016
https://app.liuyingyong.cn/build/download/f28fefa0-bb87-11ef-ae91-791115b54ea0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
var isReady=false;var onReadyCallbacks=[];
var isServiceReady=false;var onServiceReadyCallbacks=[];
var __uniConfig = {"pages":["pages/index/index","pages/login/login","pages/index/detail","pages/login/forget","pages/login/register","pages/device/device","pages/my/my","pages/login/explain","pages/index/echarts","pages/only_test/only_test","pages/only_test/ot1","pages/only_test/ot2","pages/only_test/ot3","pages/only_test/ot5"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"中鼎云医","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom","pageOrientation":"portrait"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"中鼎云医","compilerVersion":"4.15","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{}},{"path":"/pages/login/login","meta":{},"window":{}},{"path":"/pages/index/detail","meta":{},"window":{}},{"path":"/pages/login/forget","meta":{},"window":{}},{"path":"/pages/login/register","meta":{},"window":{}},{"path":"/pages/device/device","meta":{},"window":{}},{"path":"/pages/my/my","meta":{},"window":{}},{"path":"/pages/login/explain","meta":{},"window":{}},{"path":"/pages/index/echarts","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/only_test","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot1","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot2","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot3","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot5","meta":{},"window":{"navigationBarTitleText":""}}];
var __uniConfig = {"pages":["pages/index/blank","pages/index/index","pages/login/login","pages/index/detail","pages/login/forget","pages/login/register","pages/device/device","pages/my/my","pages/login/explain","pages/index/echarts","pages/only_test/only_test","pages/only_test/ot1","pages/only_test/ot2","pages/only_test/ot3","pages/only_test/ot5"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"中鼎云医","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"中鼎云医","compilerVersion":"4.36","entryPagePath":"pages/index/blank","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/blank","meta":{"isQuit":true},"window":{}},{"path":"/pages/index/index","meta":{},"window":{}},{"path":"/pages/login/login","meta":{},"window":{}},{"path":"/pages/index/detail","meta":{},"window":{}},{"path":"/pages/login/forget","meta":{},"window":{}},{"path":"/pages/login/register","meta":{},"window":{}},{"path":"/pages/device/device","meta":{},"window":{}},{"path":"/pages/my/my","meta":{},"window":{}},{"path":"/pages/login/explain","meta":{},"window":{}},{"path":"/pages/index/echarts","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/only_test","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot1","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot2","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot3","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot5","meta":{},"window":{"navigationBarTitleText":""}}];
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,9 @@
<script src="./js/voice.js"></script>
<script src="./js/crypto-js.min.js"></script>
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
<!-- 文字转拼音 -->
<script src="./js/pinyin.js"></script>
<script src="js/w_md5.js"></script>
<!-- 构建界面 -->
@ -27,8 +30,11 @@
<!-- 视频 -->
<div class="video-wrap">
<div id="shadow">
<div id="shadow-text">模型正在启动……</div>
</div>
<video id="myVideo" muted loop autoplay playsinline>
<source src="https://img.agrimedia.cn/bmsc/%E9%A3%9E%E4%B9%A620240918-175041.mp4" type="video/mp4">
<source src="./demo/ple.mp4" type="video/mp4">
</video>
</div>
<audio
@ -84,6 +90,8 @@
var Question = '';
var Subtitles = '';
let { pinyin } = pinyinPro;
function getURLParameter(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
@ -124,7 +132,7 @@
dataLines.push(line.trim());
}
});
const dataJson = dataLines.join('');
try {
if (dataJson) {
@ -137,7 +145,7 @@
console.error('解析 data 字段为 JSON 时出错:', error);
}
});
// 如果没有找到 finish_reason 为 "stop" 的事件,则返回 null 或其他默认值
return stopEvent;
}
@ -146,17 +154,33 @@
<!-- 讯飞语音识别 -->
<script>
window.onload = function () {
reset();
};
function reset() {
var videoElement = document.getElementById('myVideo');
var startTime = 5; // 开始时间(以秒为单位)
var endTime = 10; // 结束时间(以秒为单位)
var timeUpdateListener; // 保存timeupdate事件的监听器
// var onLine = 'false';
// // 在线离线
// function checkNetworkStatus() {
// if (navigator.onLine) {
// onLine = true;
// console.log('在线');
// } else {
// onLine = false;
// console.log('离线');
// }
// }
// 初始检查网络状态
// checkNetworkStatus();
// 遮罩视频
var shadowDom = document.getElementById('shadow');
var shadowText = document.getElementById('shadow-text');
// 指定段落
function playVideoSegment(startTime, endTime) {
function playVideoSegment(startTime, endTime) {
videoElement.currentTime = startTime;
setTimeout(() => {
videoElement.play();
@ -196,7 +220,7 @@
var audioElement = document.getElementById('myAudio');
var isPlaying = false; // 是否播放
audioElement.muted = true; // 先静音
// 获取页面元素
var element = document.getElementById("elementId");
@ -210,8 +234,7 @@
endRec.style.display = "none";
stopRec.style.display = "none";
var token = null;
let times = null;
@ -219,6 +242,16 @@
var user = userInfo(JSON.parse(getURLParameter('user')));
var apitoken = getURLParameter('token');
var deviceId = getURLParameter('deviceId');
var loading = getURLParameter('loading');
setTimeout(() => {
if (loading) {
shadowDom.style.display = 'none';
} else {
alert('异常')
shadowText.innerHTML = '环境异常,请检查网络'
}
}, 500);
// 获取微软token
@ -247,7 +280,7 @@
for (let i = 0; i < exampleData.length; i++) {
exampleData[i].name = demoData[exampleData[i].type]
};
// 过滤掉非对象类型的值
const filteredData = Object.entries(exampleData).filter(([key, value]) => typeof value === 'object');
@ -260,56 +293,55 @@
/*
* 实例化迅飞语音听写流式版WebAPI
*/
var seconds = 10;
var seconds = 5;
var gaptime = null;
const voice = new Voice({
var voice = new Voice({
// 服务接口认证信息
appId: '5f4ffdeb',
apiSecret: 'OGIwM2RlMjBkOTI5Mzk5YTJlMzUwODI5',
apiKey: '0b17a761b6b7174b789f639119d7e29a',
onWillStatusChange: function (oldStatus, newStatus) {
console.log(oldStatus, newStatus, '交互逻辑')
},
onWillStatusChange: function (oldStatus, newStatus) {},
onTextChange: function (text) {
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
// 2秒钟内没有说话就自动关闭
// 如果已有定时器在运行,则清除它
if (gaptime) {
clearInterval(gaptime);
};
gaptime = null;
};
// 重置倒计时
seconds = 10;
console.log(text)
seconds = 5;
gaptime = setInterval(() => {
console.log(seconds, '倒计时')
seconds--;
if (voiceTxt.innerText) {
console.log('有 text 参数'); // 如果有 text 参数,打印 1
if (text) {
clearInterval(gaptime);
gaptime = null;
seconds = 5;
// 3秒钟内没有说话,就自动关闭
// 2秒钟内没有说话,就自动关闭
if (text) {
statusTxt.value = '正在听…';
if (!isCallbackExecuted) {
clearTimeout(times);
times = setTimeout(() => {
this.stop();
statusTxt.value = '正在说话';
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
statusTxt.value = '正在听…';
console.log(new Date().getTime(), '收到文字')
const params = { msg: text };
// 判断关键字是否存在
const result = parseHealthQuery(params.msg);
console.log(JSON.stringify(result), '判断关键字是否存在')
isCallbackExecuted = true;
if (result) {
DetailDay(result.dataKey, result.date).then(res => {
let TargetData = res.data.data;
let TargetData = res.data.data;
console.log(JSON.stringify(res), '1111111111')
console.log(JSON.stringify(TargetData), '222222222222')
if (result.dataKey == 'ECGData') {
TargetData.map(item => {
@ -317,21 +349,28 @@
delete item.data_msg.list;
})
}
if (result.dataKey == 'bloodLiquid') {
let uricAcidVal = [];
let lowDensity = [];
let triacylglycerol = [];
let highDensity = [];
let cholesterol = [];
TargetData.map(item => {
item.data_msg.cholesterol = item.data_msg.cholesterol/100;
item.data_msg.highDensity = item.data_msg.highDensity/100;
item.data_msg.triacylglycerol = item.data_msg.triacylglycerol/100;
item.data_msg.uricAcidVal = item.data_msg.uricAcidVal/10000;
item.data_msg.lowDensity = item.data_msg.lowDensity/100;
item.data_msg.cholesterol = cholesterol.push((item.data_msg.cholesterol/100).toFixed(2));
item.data_msg.highDensity = highDensity.push((item.data_msg.highDensity/100).toFixed(2));
item.data_msg.triacylglycerol = triacylglycerol.push((item.data_msg.triacylglycerol/100).toFixed(2));
item.data_msg.uricAcidVal = uricAcidVal.push((item.data_msg.uricAcidVal/10).toFixed(2));
item.data_msg.lowDensity = lowDensity.push((item.data_msg.lowDensity/100).toFixed(2));
})
TargetData = '尿酸: ' + JSON.stringify(uricAcidVal) + ',高密度脂蛋白: ' + JSON.stringify(highDensity) + ',低密度脂蛋白: ' + JSON.stringify(lowDensity) + ',甘油三脂: ' + JSON.stringify(triacylglycerol) + ',总胆固醇: ' + JSON.stringify(cholesterol);
}
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。`
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。提示:回答尿酸时单位转换成“微摩尔/升”`
console.log(Question, '问题=========================问题');
/*
* 调用接口 传递关键信息 文字转语音
*/
@ -382,7 +421,7 @@
xhr.onerror = function () {
console.error('An error occurred during the transaction', xhr.statusText);
};
/*
* 关键字转换
*/
@ -472,15 +511,13 @@
isCallbackExecuted = true;
return;
}
}, 3000);
}, 2000);
}
}
} else if (seconds == 0){
clearInterval(gaptime);
closeShibie();
reset();
gaptime = null;
seconds = 10;
return;
}
}, 1000);
}
@ -495,6 +532,11 @@
// 关闭识别
endRec.addEventListener("click", function() {
closeShibie();
// 直接开始
setTimeout(() => {
startShibie();
}, 100);
});
// 暂停识别
@ -505,25 +547,26 @@
function stopPlay() {
/**暂停播放**/
if (audioElement.paused) {
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
} else {
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
}
};
function startShibie() {
/**开始识别**/
statusTxt.value = '正在听…';
voiceTxt.innerText = '';
stopRec.textContent = '暂停';
@ -531,14 +574,8 @@
// 先静音即可处理解决(提前做交互)
audioElement.muted = false;
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
seconds = 10;
audioElement.currentTime = 0;
audioElement.pause();
voice.start();
@ -553,22 +590,14 @@
voiceTxt.innerText = '';
statusTxt.value = '';
stopRec.textContent = '暂停';
voice.stop();
// 音频
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
// 视频
audioElement.pause();
audioElement.currentTime = 0;
// 视频
replayVideoSegment(0, 60);
isCallbackExecuted = false;
seconds = 10;
voice.stop();
console.log('关闭识别');
startRec.style.display = 'block';
endRec.style.display = 'none';
@ -580,7 +609,7 @@
function showModal() {
modal.style.display = 'block';
dialog.style.display = 'block';
}
}
// 隐藏弹窗和遮罩
function hideModal() {
@ -641,7 +670,7 @@
startRec.style.display = "none";
endRec.style.display = "block";
stopRec.style.display = "block";
voiceTxt.innerText = '';
NextPlayVideo(response, filterString(Subtitles, ['*', ' ']));
}).catch(e => {
hideModal();
@ -667,43 +696,23 @@
// 播放音频
audioElement.play();
console.log(new Date().getTime(), '播放音频')
// 循环视频
replayVideoSegment(60, 120);
// 监听播放技术
myAudio.addEventListener('ended', function() {
console.log('音频播放已结束!');
// 停止倒计时
startRec.style.display = 'block';
endRec.style.display = 'none';
stopRec.style.display = 'none';
statusTxt.value = '';
voiceTxt.innerText = '';
replayVideoSegment(0, 60);
hideModal()
// 播放结束重新开始监听
replayVideoSegment(0, 60);
voice.stop();
startShibie();
});
Subtitles = "";
}
// 防抖
function throttle(fn, wait) {
let lastTime = 0; // 上一次调用的时间
return function (...args) {
const now = Date.now(); // 当前时间
// 如果距离上次调用已经超过设定时间,则调用函数
if (now - lastTime > wait) {
lastTime = now; // 更新上一次调用的时间
fn.apply(this, args); // 以正确的`this`和参数调用函数
}
};
}
// 拿到的数据移除*
function filterString(str, charsToRemove) {
// 这里的正则表达式是通过将charsToRemove数组中的字符转换为字符类character class来构建的
@ -726,15 +735,15 @@
demoData = {
bloodGlucose: "血糖",
SleepDatas: "睡眠",
bloodOxygen: "血氧",
bloodOxygen: ['血氧', '血氧饱和度'],
bloodPressure: '血压',
meiTuo: '梅脱',
pulseReat: '心率',
bodyTemperature: '体温',
ECGData: '心电图',
bloodLiquid: ['血脂', '血液', '尿酸'],
bloodLiquid: ['血脂', '血液', '尿酸', '胆固醇', '甘油三脂', '高密度脂蛋白', '低密度脂蛋白'],
bodyData: '身体成分',
stepIndex: ['运动', '步数']
stepIndex: ['运动', '步数']
};
}
@ -745,16 +754,22 @@
const day = today.getDate();
// 初始化日期为今天
let targetDate = new Date(year, month, day);
let targetDate = new Date(year, month - 1, day);
// 检查时间词并设置目标日期
if (query.includes("昨天")) {
targetDate.setDate(day - 1);
} else if (query.includes("前天")) {
targetDate.setDate(day - 2);
}
const formattedDate = `${targetDate.getFullYear()}-${('0' + targetDate.getMonth()).slice(-2)}-${('0' + targetDate.getDate()).slice(-2)}`;
let offsetDays = 0; // 用于存储需要偏移的天数
if (query.includes("昨天")) {
offsetDays = -1;
} else if (query.includes("前天")) {
offsetDays = -2;
}
// 应用天数偏移,并正确处理跨月或跨年情况
targetDate.setDate(targetDate.getDate() + offsetDays);
// 格式化日期,确保月份和日期都是两位数
const formattedDate = `${targetDate.getFullYear()}-${String(targetDate.getMonth() + 1).padStart(2, '0')}-${String(targetDate.getDate()).padStart(2, '0')}`;
// 创建一个辅助函数来检查 bloodLiquid 对象是否包含查询字符串
function isBloodLiquidMatch(bloodLiquidData, query) {
@ -763,7 +778,7 @@
// 在查询逻辑中使用这个辅助函数
for (let key in demoData) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' ) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' || typeof demoData[key] === 'object' && key === 'bloodOxygen' ) {
if (isBloodLiquidMatch(demoData[key], query)) {
key === 'stepIndex'? key = 'step_split' : ''; // 修改步数参数
return {
@ -776,13 +791,18 @@
dataKey: key,
date: formattedDate
};
}
} else if (pinyin(query, { toneType: 'none' }).replace(/\s/g, '').includes("xueyang")) { // 不容易识别转拼音,上面其实都可以优化
return {
dataKey: 'bloodOxygen',
date: formattedDate
};
}
}
// 如果没有找到匹配的数据项则返回null或错误信息这里选择返回null
return null;
}
}
};
</script>
@ -815,6 +835,30 @@
border-radius: 10px;
}
#shadow {
position: fixed;
z-index: 99999;
width: 100%;
height: 100vh;
left: 0;
top: 0;
background-color: #06193a;
}
#shadow-text {
width: 100%;
height: 100vh;
position: absolute;
text-align: center;
line-height: 100vh;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0 auto;
color: #fff;
}
#myVideo {
width: 100%;
height: 100% !important;

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -110,6 +110,7 @@
};
// 连接WebSocket
connectWebSocket() {
console.log('连接WebSocket')
return this.getWebSocketUrl().then(url => {
let iatWS;
if ('WebSocket' in window) {
@ -122,8 +123,11 @@
}
this.webSocket = iatWS;
this.setStatus('init');
iatWS.onopen = e => {
this.setStatus('ing');
console.log('ws开启重新开始录音');
// 重新开始录音
setTimeout(() => {
this.webSocketSend();
@ -140,6 +144,18 @@
};
})
};
// 防抖函数
debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
// 初始化浏览器录音
recorderInit() {
// 创建音频环境
@ -216,9 +232,10 @@
};
// 向webSocket发送数据(音频二进制数据经过Base64处理)
webSocketSend() {
console.log('发送数据')
if (this.webSocket.readyState !== 1) return false;
// 音频数据
const audioData = this.audioData.splice(0, 1280);
let audioData = this.audioData.splice(0, 1280);
const params = {
common: {
app_id: this.appId,
@ -237,14 +254,17 @@
audio: this.toBase64(audioData)
}
};
console.log(params, 'socket数据');
// 发送数据
this.webSocket.send(JSON.stringify(params));
this.handlerInterval = setInterval(() => {
// websocket未连接
if (this.webSocket.readyState !== 1) {
this.audioData = [];
clearInterval(this.handlerInterval);
return false;
return false;
};
if (this.audioData.length === 0) {
if (this.status === 'end') {
@ -312,9 +332,10 @@
this.webSocket.close();
}
};
// 启动录音
recorderStart() {
if (!this.audioContext) {
if (!this.audioContext) {
this.recorderInit();
} else {
this.audioContext.resume();
@ -340,8 +361,10 @@
this.setResultText({ resultText: '', resultTextTemp: '' });
};
// 停止
stop() {
stop() {
console.log('停了停了停了停了停了停了停了停了停了停了');
this.recorderStop();
this.webSocket.close();
};
};
}));

View File

@ -1 +1 @@
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__24DA8DD","name":"中鼎云医","version":{"name":"1.2.5","code":125},"description":"中鼎云医","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"VideoPlayer":{},"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":true,"delay":0,"target":"id:1","waiting":true},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"screenOrientation":"portrait","icons":{"android":{"hdpi":"icon-android-hdpi.png","xhdpi":"icon-android-xhdpi.png","xxhdpi":"icon-android-xxhdpi.png","xxxhdpi":"icon-android-xxxhdpi.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"},"prerendered":"false"}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"],"packagename":"uni.UNI24DA8DD","aliasname":"platform","password":"aB6ADjKOYCOnZRmpzM7ptg==","keystore":"google-keystore.keystore","custompermissions":true},"apple":{"dSYMs":false,"devices":"universal"},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}},"orientation":"portrait-primary"},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.15","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html","adid":"123262070412"},"screenOrientation":["portrait-primary","portrait-secondary"]}
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__24DA8DD","name":"中鼎云医","version":{"name":"1.2.8","code":128},"description":"中鼎云医","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"VideoPlayer":{},"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":true,"delay":0,"target":"id:1","waiting":true},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"compatible":{"ignoreVersion":true},"distribute":{"icons":{"android":{"hdpi":"icon-android-hdpi.png","xhdpi":"icon-android-xhdpi.png","xxhdpi":"icon-android-xxhdpi.png","xxxhdpi":"icon-android-xxxhdpi.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"},"prerendered":"false"}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"],"packagename":"uni.UNI24DA8DD","aliasname":"platform","password":"aB6ADjKOYCOnZRmpzM7ptg==","keystore":"google-keystore.keystore","custompermissions":true},"apple":{"dSYMs":false,"devices":"universal"},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}},"orientation":"portrait-primary"},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.36","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html","adid":"123262070412"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
var isReady=false;var onReadyCallbacks=[];
var isServiceReady=false;var onServiceReadyCallbacks=[];
var __uniConfig = {"pages":["pages/index/index","pages/login/login","pages/index/detail","pages/login/forget","pages/login/register","pages/device/device","pages/my/my","pages/login/explain","pages/index/echarts","pages/only_test/only_test","pages/only_test/ot1","pages/only_test/ot2","pages/only_test/ot3","pages/only_test/ot5"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"中鼎云医","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom","pageOrientation":"portrait"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"中鼎云医","compilerVersion":"4.15","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{}},{"path":"/pages/login/login","meta":{},"window":{}},{"path":"/pages/index/detail","meta":{},"window":{}},{"path":"/pages/login/forget","meta":{},"window":{}},{"path":"/pages/login/register","meta":{},"window":{}},{"path":"/pages/device/device","meta":{},"window":{}},{"path":"/pages/my/my","meta":{},"window":{}},{"path":"/pages/login/explain","meta":{},"window":{}},{"path":"/pages/index/echarts","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/only_test","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot1","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot2","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot3","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot5","meta":{},"window":{"navigationBarTitleText":""}}];
var __uniConfig = {"pages":["pages/index/blank","pages/index/index","pages/login/login","pages/index/detail","pages/login/forget","pages/login/register","pages/device/device","pages/my/my","pages/login/explain","pages/index/echarts","pages/only_test/only_test","pages/only_test/ot1","pages/only_test/ot2","pages/only_test/ot3","pages/only_test/ot5"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"中鼎云医","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"中鼎云医","compilerVersion":"4.36","entryPagePath":"pages/index/blank","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/blank","meta":{"isQuit":true},"window":{}},{"path":"/pages/index/index","meta":{},"window":{}},{"path":"/pages/login/login","meta":{},"window":{}},{"path":"/pages/index/detail","meta":{},"window":{}},{"path":"/pages/login/forget","meta":{},"window":{}},{"path":"/pages/login/register","meta":{},"window":{}},{"path":"/pages/device/device","meta":{},"window":{}},{"path":"/pages/my/my","meta":{},"window":{}},{"path":"/pages/login/explain","meta":{},"window":{}},{"path":"/pages/index/echarts","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/only_test","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot1","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot2","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot3","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot5","meta":{},"window":{"navigationBarTitleText":""}}];
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,9 @@
<script src="./js/voice.js"></script>
<script src="./js/crypto-js.min.js"></script>
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
<!-- 文字转拼音 -->
<script src="./js/pinyin.js"></script>
<script src="js/w_md5.js"></script>
<!-- 构建界面 -->
@ -27,8 +30,11 @@
<!-- 视频 -->
<div class="video-wrap">
<div id="shadow">
<div id="shadow-text">模型正在启动……</div>
</div>
<video id="myVideo" muted loop autoplay playsinline>
<source src="https://img.agrimedia.cn/bmsc/%E9%A3%9E%E4%B9%A620240918-175041.mp4" type="video/mp4">
<source src="./demo/ple.mp4" type="video/mp4">
</video>
</div>
<audio
@ -84,6 +90,8 @@
var Question = '';
var Subtitles = '';
let { pinyin } = pinyinPro;
function getURLParameter(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
@ -124,7 +132,7 @@
dataLines.push(line.trim());
}
});
const dataJson = dataLines.join('');
try {
if (dataJson) {
@ -137,7 +145,7 @@
console.error('解析 data 字段为 JSON 时出错:', error);
}
});
// 如果没有找到 finish_reason 为 "stop" 的事件,则返回 null 或其他默认值
return stopEvent;
}
@ -146,17 +154,33 @@
<!-- 讯飞语音识别 -->
<script>
window.onload = function () {
reset();
};
function reset() {
var videoElement = document.getElementById('myVideo');
var startTime = 5; // 开始时间(以秒为单位)
var endTime = 10; // 结束时间(以秒为单位)
var timeUpdateListener; // 保存timeupdate事件的监听器
// var onLine = 'false';
// // 在线离线
// function checkNetworkStatus() {
// if (navigator.onLine) {
// onLine = true;
// console.log('在线');
// } else {
// onLine = false;
// console.log('离线');
// }
// }
// 初始检查网络状态
// checkNetworkStatus();
// 遮罩视频
var shadowDom = document.getElementById('shadow');
var shadowText = document.getElementById('shadow-text');
// 指定段落
function playVideoSegment(startTime, endTime) {
function playVideoSegment(startTime, endTime) {
videoElement.currentTime = startTime;
setTimeout(() => {
videoElement.play();
@ -196,7 +220,7 @@
var audioElement = document.getElementById('myAudio');
var isPlaying = false; // 是否播放
audioElement.muted = true; // 先静音
// 获取页面元素
var element = document.getElementById("elementId");
@ -210,8 +234,7 @@
endRec.style.display = "none";
stopRec.style.display = "none";
var token = null;
let times = null;
@ -219,6 +242,16 @@
var user = userInfo(JSON.parse(getURLParameter('user')));
var apitoken = getURLParameter('token');
var deviceId = getURLParameter('deviceId');
var loading = getURLParameter('loading');
setTimeout(() => {
if (loading) {
shadowDom.style.display = 'none';
} else {
alert('异常')
shadowText.innerHTML = '环境异常,请检查网络'
}
}, 500);
// 获取微软token
@ -247,7 +280,7 @@
for (let i = 0; i < exampleData.length; i++) {
exampleData[i].name = demoData[exampleData[i].type]
};
// 过滤掉非对象类型的值
const filteredData = Object.entries(exampleData).filter(([key, value]) => typeof value === 'object');
@ -260,56 +293,55 @@
/*
* 实例化迅飞语音听写流式版WebAPI
*/
var seconds = 10;
var seconds = 5;
var gaptime = null;
const voice = new Voice({
var voice = new Voice({
// 服务接口认证信息
appId: '5f4ffdeb',
apiSecret: 'OGIwM2RlMjBkOTI5Mzk5YTJlMzUwODI5',
apiKey: '0b17a761b6b7174b789f639119d7e29a',
onWillStatusChange: function (oldStatus, newStatus) {
console.log(oldStatus, newStatus, '交互逻辑')
},
onWillStatusChange: function (oldStatus, newStatus) {},
onTextChange: function (text) {
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
// 2秒钟内没有说话就自动关闭
// 如果已有定时器在运行,则清除它
if (gaptime) {
clearInterval(gaptime);
};
gaptime = null;
};
// 重置倒计时
seconds = 10;
console.log(text)
seconds = 5;
gaptime = setInterval(() => {
console.log(seconds, '倒计时')
seconds--;
if (voiceTxt.innerText) {
console.log('有 text 参数'); // 如果有 text 参数,打印 1
if (text) {
clearInterval(gaptime);
gaptime = null;
seconds = 5;
// 3秒钟内没有说话,就自动关闭
// 2秒钟内没有说话,就自动关闭
if (text) {
statusTxt.value = '正在听…';
if (!isCallbackExecuted) {
clearTimeout(times);
times = setTimeout(() => {
this.stop();
statusTxt.value = '正在说话';
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
statusTxt.value = '正在听…';
console.log(new Date().getTime(), '收到文字')
const params = { msg: text };
// 判断关键字是否存在
const result = parseHealthQuery(params.msg);
console.log(JSON.stringify(result), '判断关键字是否存在')
isCallbackExecuted = true;
if (result) {
DetailDay(result.dataKey, result.date).then(res => {
let TargetData = res.data.data;
let TargetData = res.data.data;
console.log(JSON.stringify(res), '1111111111')
console.log(JSON.stringify(TargetData), '222222222222')
if (result.dataKey == 'ECGData') {
TargetData.map(item => {
@ -317,21 +349,28 @@
delete item.data_msg.list;
})
}
if (result.dataKey == 'bloodLiquid') {
let uricAcidVal = [];
let lowDensity = [];
let triacylglycerol = [];
let highDensity = [];
let cholesterol = [];
TargetData.map(item => {
item.data_msg.cholesterol = item.data_msg.cholesterol/100;
item.data_msg.highDensity = item.data_msg.highDensity/100;
item.data_msg.triacylglycerol = item.data_msg.triacylglycerol/100;
item.data_msg.uricAcidVal = item.data_msg.uricAcidVal/10000;
item.data_msg.lowDensity = item.data_msg.lowDensity/100;
item.data_msg.cholesterol = cholesterol.push((item.data_msg.cholesterol/100).toFixed(2));
item.data_msg.highDensity = highDensity.push((item.data_msg.highDensity/100).toFixed(2));
item.data_msg.triacylglycerol = triacylglycerol.push((item.data_msg.triacylglycerol/100).toFixed(2));
item.data_msg.uricAcidVal = uricAcidVal.push((item.data_msg.uricAcidVal/10).toFixed(2));
item.data_msg.lowDensity = lowDensity.push((item.data_msg.lowDensity/100).toFixed(2));
})
TargetData = '尿酸: ' + JSON.stringify(uricAcidVal) + ',高密度脂蛋白: ' + JSON.stringify(highDensity) + ',低密度脂蛋白: ' + JSON.stringify(lowDensity) + ',甘油三脂: ' + JSON.stringify(triacylglycerol) + ',总胆固醇: ' + JSON.stringify(cholesterol);
}
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。`
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。提示:回答尿酸时单位转换成“微摩尔/升”`
console.log(Question, '问题=========================问题');
/*
* 调用接口 传递关键信息 文字转语音
*/
@ -382,7 +421,7 @@
xhr.onerror = function () {
console.error('An error occurred during the transaction', xhr.statusText);
};
/*
* 关键字转换
*/
@ -472,15 +511,13 @@
isCallbackExecuted = true;
return;
}
}, 3000);
}, 2000);
}
}
} else if (seconds == 0){
clearInterval(gaptime);
closeShibie();
reset();
gaptime = null;
seconds = 10;
return;
}
}, 1000);
}
@ -495,6 +532,11 @@
// 关闭识别
endRec.addEventListener("click", function() {
closeShibie();
// 直接开始
setTimeout(() => {
startShibie();
}, 100);
});
// 暂停识别
@ -505,25 +547,26 @@
function stopPlay() {
/**暂停播放**/
if (audioElement.paused) {
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
} else {
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
}
};
function startShibie() {
/**开始识别**/
statusTxt.value = '正在听…';
voiceTxt.innerText = '';
stopRec.textContent = '暂停';
@ -531,14 +574,8 @@
// 先静音即可处理解决(提前做交互)
audioElement.muted = false;
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
seconds = 10;
audioElement.currentTime = 0;
audioElement.pause();
voice.start();
@ -553,22 +590,14 @@
voiceTxt.innerText = '';
statusTxt.value = '';
stopRec.textContent = '暂停';
voice.stop();
// 音频
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
// 视频
audioElement.pause();
audioElement.currentTime = 0;
// 视频
replayVideoSegment(0, 60);
isCallbackExecuted = false;
seconds = 10;
voice.stop();
console.log('关闭识别');
startRec.style.display = 'block';
endRec.style.display = 'none';
@ -580,7 +609,7 @@
function showModal() {
modal.style.display = 'block';
dialog.style.display = 'block';
}
}
// 隐藏弹窗和遮罩
function hideModal() {
@ -641,7 +670,7 @@
startRec.style.display = "none";
endRec.style.display = "block";
stopRec.style.display = "block";
voiceTxt.innerText = '';
NextPlayVideo(response, filterString(Subtitles, ['*', ' ']));
}).catch(e => {
hideModal();
@ -667,43 +696,23 @@
// 播放音频
audioElement.play();
console.log(new Date().getTime(), '播放音频')
// 循环视频
replayVideoSegment(60, 120);
// 监听播放技术
myAudio.addEventListener('ended', function() {
console.log('音频播放已结束!');
// 停止倒计时
startRec.style.display = 'block';
endRec.style.display = 'none';
stopRec.style.display = 'none';
statusTxt.value = '';
voiceTxt.innerText = '';
replayVideoSegment(0, 60);
hideModal()
// 播放结束重新开始监听
replayVideoSegment(0, 60);
voice.stop();
startShibie();
});
Subtitles = "";
}
// 防抖
function throttle(fn, wait) {
let lastTime = 0; // 上一次调用的时间
return function (...args) {
const now = Date.now(); // 当前时间
// 如果距离上次调用已经超过设定时间,则调用函数
if (now - lastTime > wait) {
lastTime = now; // 更新上一次调用的时间
fn.apply(this, args); // 以正确的`this`和参数调用函数
}
};
}
// 拿到的数据移除*
function filterString(str, charsToRemove) {
// 这里的正则表达式是通过将charsToRemove数组中的字符转换为字符类character class来构建的
@ -726,15 +735,15 @@
demoData = {
bloodGlucose: "血糖",
SleepDatas: "睡眠",
bloodOxygen: "血氧",
bloodOxygen: ['血氧', '血氧饱和度'],
bloodPressure: '血压',
meiTuo: '梅脱',
pulseReat: '心率',
bodyTemperature: '体温',
ECGData: '心电图',
bloodLiquid: ['血脂', '血液', '尿酸'],
bloodLiquid: ['血脂', '血液', '尿酸', '胆固醇', '甘油三脂', '高密度脂蛋白', '低密度脂蛋白'],
bodyData: '身体成分',
stepIndex: ['运动', '步数']
stepIndex: ['运动', '步数']
};
}
@ -745,16 +754,22 @@
const day = today.getDate();
// 初始化日期为今天
let targetDate = new Date(year, month, day);
let targetDate = new Date(year, month - 1, day);
// 检查时间词并设置目标日期
if (query.includes("昨天")) {
targetDate.setDate(day - 1);
} else if (query.includes("前天")) {
targetDate.setDate(day - 2);
}
const formattedDate = `${targetDate.getFullYear()}-${('0' + targetDate.getMonth()).slice(-2)}-${('0' + targetDate.getDate()).slice(-2)}`;
let offsetDays = 0; // 用于存储需要偏移的天数
if (query.includes("昨天")) {
offsetDays = -1;
} else if (query.includes("前天")) {
offsetDays = -2;
}
// 应用天数偏移,并正确处理跨月或跨年情况
targetDate.setDate(targetDate.getDate() + offsetDays);
// 格式化日期,确保月份和日期都是两位数
const formattedDate = `${targetDate.getFullYear()}-${String(targetDate.getMonth() + 1).padStart(2, '0')}-${String(targetDate.getDate()).padStart(2, '0')}`;
// 创建一个辅助函数来检查 bloodLiquid 对象是否包含查询字符串
function isBloodLiquidMatch(bloodLiquidData, query) {
@ -763,7 +778,7 @@
// 在查询逻辑中使用这个辅助函数
for (let key in demoData) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' ) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' || typeof demoData[key] === 'object' && key === 'bloodOxygen' ) {
if (isBloodLiquidMatch(demoData[key], query)) {
key === 'stepIndex'? key = 'step_split' : ''; // 修改步数参数
return {
@ -776,13 +791,18 @@
dataKey: key,
date: formattedDate
};
}
} else if (pinyin(query, { toneType: 'none' }).replace(/\s/g, '').includes("xueyang")) { // 不容易识别转拼音,上面其实都可以优化
return {
dataKey: 'bloodOxygen',
date: formattedDate
};
}
}
// 如果没有找到匹配的数据项则返回null或错误信息这里选择返回null
return null;
}
}
};
</script>
@ -815,6 +835,30 @@
border-radius: 10px;
}
#shadow {
position: fixed;
z-index: 99999;
width: 100%;
height: 100vh;
left: 0;
top: 0;
background-color: #06193a;
}
#shadow-text {
width: 100%;
height: 100vh;
position: absolute;
text-align: center;
line-height: 100vh;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0 auto;
color: #fff;
}
#myVideo {
width: 100%;
height: 100% !important;

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -110,6 +110,7 @@
};
// 连接WebSocket
connectWebSocket() {
console.log('连接WebSocket')
return this.getWebSocketUrl().then(url => {
let iatWS;
if ('WebSocket' in window) {
@ -122,8 +123,11 @@
}
this.webSocket = iatWS;
this.setStatus('init');
iatWS.onopen = e => {
this.setStatus('ing');
console.log('ws开启重新开始录音');
// 重新开始录音
setTimeout(() => {
this.webSocketSend();
@ -140,6 +144,18 @@
};
})
};
// 防抖函数
debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
// 初始化浏览器录音
recorderInit() {
// 创建音频环境
@ -216,9 +232,10 @@
};
// 向webSocket发送数据(音频二进制数据经过Base64处理)
webSocketSend() {
console.log('发送数据')
if (this.webSocket.readyState !== 1) return false;
// 音频数据
const audioData = this.audioData.splice(0, 1280);
let audioData = this.audioData.splice(0, 1280);
const params = {
common: {
app_id: this.appId,
@ -237,14 +254,17 @@
audio: this.toBase64(audioData)
}
};
console.log(params, 'socket数据');
// 发送数据
this.webSocket.send(JSON.stringify(params));
this.handlerInterval = setInterval(() => {
// websocket未连接
if (this.webSocket.readyState !== 1) {
this.audioData = [];
clearInterval(this.handlerInterval);
return false;
return false;
};
if (this.audioData.length === 0) {
if (this.status === 'end') {
@ -312,9 +332,10 @@
this.webSocket.close();
}
};
// 启动录音
recorderStart() {
if (!this.audioContext) {
if (!this.audioContext) {
this.recorderInit();
} else {
this.audioContext.resume();
@ -340,8 +361,10 @@
this.setResultText({ resultText: '', resultTextTemp: '' });
};
// 停止
stop() {
stop() {
console.log('停了停了停了停了停了停了停了停了停了停了');
this.recorderStop();
this.webSocket.close();
};
};
}));

View File

@ -1 +1 @@
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__24DA8DD","name":"中鼎云医","version":{"name":"1.2.5","code":125},"description":"中鼎云医","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"VideoPlayer":{},"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"screenOrientation":"portrait","icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.15","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"},"screenOrientation":["portrait-primary","portrait-secondary"]}
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__24DA8DD","name":"中鼎云医","version":{"name":"1.2.8","code":128},"description":"中鼎云医","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"VideoPlayer":{},"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"compatible":{"ignoreVersion":true},"distribute":{"icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.36","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
var isReady=false;var onReadyCallbacks=[];
var isServiceReady=false;var onServiceReadyCallbacks=[];
var __uniConfig = {"pages":["pages/index/index","pages/login/login","pages/index/detail","pages/login/forget","pages/login/register","pages/device/device","pages/my/my","pages/login/explain","pages/index/echarts","pages/only_test/only_test","pages/only_test/ot1","pages/only_test/ot2","pages/only_test/ot3","pages/only_test/ot5"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"中鼎云医","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom","pageOrientation":"portrait"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"中鼎云医","compilerVersion":"4.15","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{}},{"path":"/pages/login/login","meta":{},"window":{}},{"path":"/pages/index/detail","meta":{},"window":{}},{"path":"/pages/login/forget","meta":{},"window":{}},{"path":"/pages/login/register","meta":{},"window":{}},{"path":"/pages/device/device","meta":{},"window":{}},{"path":"/pages/my/my","meta":{},"window":{}},{"path":"/pages/login/explain","meta":{},"window":{}},{"path":"/pages/index/echarts","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/only_test","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot1","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot2","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot3","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot5","meta":{},"window":{"navigationBarTitleText":""}}];
var __uniConfig = {"pages":["pages/index/blank","pages/index/index","pages/login/login","pages/index/detail","pages/login/forget","pages/login/register","pages/device/device","pages/my/my","pages/login/explain","pages/index/echarts","pages/only_test/only_test","pages/only_test/ot1","pages/only_test/ot2","pages/only_test/ot3","pages/only_test/ot5"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"中鼎云医","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"中鼎云医","compilerVersion":"4.36","entryPagePath":"pages/index/blank","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/blank","meta":{"isQuit":true},"window":{}},{"path":"/pages/index/index","meta":{},"window":{}},{"path":"/pages/login/login","meta":{},"window":{}},{"path":"/pages/index/detail","meta":{},"window":{}},{"path":"/pages/login/forget","meta":{},"window":{}},{"path":"/pages/login/register","meta":{},"window":{}},{"path":"/pages/device/device","meta":{},"window":{}},{"path":"/pages/my/my","meta":{},"window":{}},{"path":"/pages/login/explain","meta":{},"window":{}},{"path":"/pages/index/echarts","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/only_test","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot1","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot2","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot3","meta":{},"window":{"navigationBarTitleText":""}},{"path":"/pages/only_test/ot5","meta":{},"window":{"navigationBarTitleText":""}}];
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,9 @@
<script src="./js/voice.js"></script>
<script src="./js/crypto-js.min.js"></script>
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
<!-- 文字转拼音 -->
<script src="./js/pinyin.js"></script>
<script src="js/w_md5.js"></script>
<!-- 构建界面 -->
@ -27,8 +30,11 @@
<!-- 视频 -->
<div class="video-wrap">
<div id="shadow">
<div id="shadow-text">模型正在启动……</div>
</div>
<video id="myVideo" muted loop autoplay playsinline>
<source src="https://img.agrimedia.cn/bmsc/%E9%A3%9E%E4%B9%A620240918-175041.mp4" type="video/mp4">
<source src="./demo/ple.mp4" type="video/mp4">
</video>
</div>
<audio
@ -84,6 +90,8 @@
var Question = '';
var Subtitles = '';
let { pinyin } = pinyinPro;
function getURLParameter(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
@ -124,7 +132,7 @@
dataLines.push(line.trim());
}
});
const dataJson = dataLines.join('');
try {
if (dataJson) {
@ -137,7 +145,7 @@
console.error('解析 data 字段为 JSON 时出错:', error);
}
});
// 如果没有找到 finish_reason 为 "stop" 的事件,则返回 null 或其他默认值
return stopEvent;
}
@ -146,17 +154,33 @@
<!-- 讯飞语音识别 -->
<script>
window.onload = function () {
reset();
};
function reset() {
var videoElement = document.getElementById('myVideo');
var startTime = 5; // 开始时间(以秒为单位)
var endTime = 10; // 结束时间(以秒为单位)
var timeUpdateListener; // 保存timeupdate事件的监听器
// var onLine = 'false';
// // 在线离线
// function checkNetworkStatus() {
// if (navigator.onLine) {
// onLine = true;
// console.log('在线');
// } else {
// onLine = false;
// console.log('离线');
// }
// }
// 初始检查网络状态
// checkNetworkStatus();
// 遮罩视频
var shadowDom = document.getElementById('shadow');
var shadowText = document.getElementById('shadow-text');
// 指定段落
function playVideoSegment(startTime, endTime) {
function playVideoSegment(startTime, endTime) {
videoElement.currentTime = startTime;
setTimeout(() => {
videoElement.play();
@ -196,7 +220,7 @@
var audioElement = document.getElementById('myAudio');
var isPlaying = false; // 是否播放
audioElement.muted = true; // 先静音
// 获取页面元素
var element = document.getElementById("elementId");
@ -210,8 +234,7 @@
endRec.style.display = "none";
stopRec.style.display = "none";
var token = null;
let times = null;
@ -219,6 +242,16 @@
var user = userInfo(JSON.parse(getURLParameter('user')));
var apitoken = getURLParameter('token');
var deviceId = getURLParameter('deviceId');
var loading = getURLParameter('loading');
setTimeout(() => {
if (loading) {
shadowDom.style.display = 'none';
} else {
alert('异常')
shadowText.innerHTML = '环境异常,请检查网络'
}
}, 500);
// 获取微软token
@ -247,7 +280,7 @@
for (let i = 0; i < exampleData.length; i++) {
exampleData[i].name = demoData[exampleData[i].type]
};
// 过滤掉非对象类型的值
const filteredData = Object.entries(exampleData).filter(([key, value]) => typeof value === 'object');
@ -260,55 +293,55 @@
/*
* 实例化迅飞语音听写流式版WebAPI
*/
var seconds = 10;
var seconds = 5;
var gaptime = null;
const voice = new Voice({
var voice = new Voice({
// 服务接口认证信息
appId: '5f4ffdeb',
apiSecret: 'OGIwM2RlMjBkOTI5Mzk5YTJlMzUwODI5',
apiKey: '0b17a761b6b7174b789f639119d7e29a',
onWillStatusChange: function (oldStatus, newStatus) {
console.log(oldStatus, newStatus, '交互逻辑')
},
onWillStatusChange: function (oldStatus, newStatus) {},
onTextChange: function (text) {
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
// 2秒钟内没有说话就自动关闭
// 如果已有定时器在运行,则清除它
if (gaptime) {
clearInterval(gaptime);
};
gaptime = null;
};
// 重置倒计时
seconds = 10;
console.log(text)
seconds = 5;
gaptime = setInterval(() => {
console.log(seconds, '倒计时')
seconds--;
if (voiceTxt.innerText) {
console.log('有 text 参数'); // 如果有 text 参数,打印 1
if (text) {
clearInterval(gaptime);
gaptime = null;
seconds = 5;
// 3秒钟内没有说话,就自动关闭
// 2秒钟内没有说话,就自动关闭
if (text) {
statusTxt.value = '正在听…';
if (!isCallbackExecuted) {
clearTimeout(times);
times = setTimeout(() => {
this.stop();
// 监听识别结果的变化
voiceTxt.innerText = text;
marquee("marquee", "voice-txt");
statusTxt.value = '正在听…';
console.log(new Date().getTime(), '收到文字')
const params = { msg: text };
// 判断关键字是否存在
const result = parseHealthQuery(params.msg);
console.log(JSON.stringify(result), '判断关键字是否存在')
isCallbackExecuted = true;
if (result) {
DetailDay(result.dataKey, result.date).then(res => {
let TargetData = res.data.data;
let TargetData = res.data.data;
console.log(JSON.stringify(res), '1111111111')
console.log(JSON.stringify(TargetData), '222222222222')
if (result.dataKey == 'ECGData') {
TargetData.map(item => {
@ -316,21 +349,28 @@
delete item.data_msg.list;
})
}
if (result.dataKey == 'bloodLiquid') {
let uricAcidVal = [];
let lowDensity = [];
let triacylglycerol = [];
let highDensity = [];
let cholesterol = [];
TargetData.map(item => {
item.data_msg.cholesterol = item.data_msg.cholesterol/100;
item.data_msg.highDensity = item.data_msg.highDensity/100;
item.data_msg.triacylglycerol = item.data_msg.triacylglycerol/100;
item.data_msg.uricAcidVal = item.data_msg.uricAcidVal/10000;
item.data_msg.lowDensity = item.data_msg.lowDensity/100;
item.data_msg.cholesterol = cholesterol.push((item.data_msg.cholesterol/100).toFixed(2));
item.data_msg.highDensity = highDensity.push((item.data_msg.highDensity/100).toFixed(2));
item.data_msg.triacylglycerol = triacylglycerol.push((item.data_msg.triacylglycerol/100).toFixed(2));
item.data_msg.uricAcidVal = uricAcidVal.push((item.data_msg.uricAcidVal/10).toFixed(2));
item.data_msg.lowDensity = lowDensity.push((item.data_msg.lowDensity/100).toFixed(2));
})
TargetData = '尿酸: ' + JSON.stringify(uricAcidVal) + ',高密度脂蛋白: ' + JSON.stringify(highDensity) + ',低密度脂蛋白: ' + JSON.stringify(lowDensity) + ',甘油三脂: ' + JSON.stringify(triacylglycerol) + ',总胆固醇: ' + JSON.stringify(cholesterol);
}
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。`
Question = `请模仿全科医生的口吻与我: ${user}对话,我最近测量的${result.dataKey}数据为${JSON.stringify(TargetData)}, #提示data_msg为值hour_minute为检测时间。#提示:“[]”表示数据为空,请在小程序上传数据。#限制:回复不要带英文,要都转化成汉语。#限制回复内容控制在150字。#限制:忽略“压力指数、疲劳指数、心肌炎风险、冠心病风险和动脉硬化”等数据。提示:回答尿酸时单位转换成“微摩尔/升”`
console.log(Question, '问题=========================问题');
/*
* 调用接口 传递关键信息 文字转语音
*/
@ -381,7 +421,7 @@
xhr.onerror = function () {
console.error('An error occurred during the transaction', xhr.statusText);
};
/*
* 关键字转换
*/
@ -471,11 +511,13 @@
isCallbackExecuted = true;
return;
}
}, 3000);
}, 2000);
}
}
} else if (seconds == 0){
reset();
clearInterval(gaptime);
closeShibie();
return;
}
}, 1000);
}
@ -490,6 +532,11 @@
// 关闭识别
endRec.addEventListener("click", function() {
closeShibie();
// 直接开始
setTimeout(() => {
startShibie();
}, 100);
});
// 暂停识别
@ -500,25 +547,26 @@
function stopPlay() {
/**暂停播放**/
if (audioElement.paused) {
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
audioElement.play();
videoElement.play();
isPlaying = true;
stopRec.textContent = '暂停';
statusTxt.value = '正在播放';
endRec.style.display = 'block';
} else {
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
audioElement.pause();
videoElement.pause();
isPlaying = false;
stopRec.textContent = '继续播放';
statusTxt.value = '已暂停';
endRec.style.display = 'none';
}
};
function startShibie() {
/**开始识别**/
statusTxt.value = '正在听…';
voiceTxt.innerText = '';
stopRec.textContent = '暂停';
@ -526,14 +574,8 @@
// 先静音即可处理解决(提前做交互)
audioElement.muted = false;
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
seconds = 10;
audioElement.currentTime = 0;
audioElement.pause();
voice.start();
@ -544,28 +586,18 @@
}
function closeShibie() {
reset();
/**关闭识别**/
voiceTxt.innerText = '';
statusTxt.value = '';
stopRec.textContent = '暂停';
voice.stop();
// 音频
// 检查是否可以播放,避免中断
if (!audioElement.paused) {
audioElement.currentTime = 0;
audioElement.pause();
};
// 视频
audioElement.pause();
audioElement.currentTime = 0;
// 视频
replayVideoSegment(0, 60);
isCallbackExecuted = false;
seconds = 10;
voice.stop();
console.log('关闭识别');
startRec.style.display = 'block';
endRec.style.display = 'none';
@ -577,7 +609,7 @@
function showModal() {
modal.style.display = 'block';
dialog.style.display = 'block';
}
}
// 隐藏弹窗和遮罩
function hideModal() {
@ -638,7 +670,7 @@
startRec.style.display = "none";
endRec.style.display = "block";
stopRec.style.display = "block";
voiceTxt.innerText = '';
NextPlayVideo(response, filterString(Subtitles, ['*', ' ']));
}).catch(e => {
hideModal();
@ -664,43 +696,23 @@
// 播放音频
audioElement.play();
console.log(new Date().getTime(), '播放音频')
// 循环视频
replayVideoSegment(60, 120);
// 监听播放技术
myAudio.addEventListener('ended', function() {
console.log('音频播放已结束!');
// 停止倒计时
startRec.style.display = 'block';
endRec.style.display = 'none';
stopRec.style.display = 'none';
statusTxt.value = '';
voiceTxt.innerText = '';
replayVideoSegment(0, 60);
hideModal()
// 播放结束重新开始监听
replayVideoSegment(0, 60);
voice.stop();
startShibie();
});
Subtitles = "";
}
// 防抖
function throttle(fn, wait) {
let lastTime = 0; // 上一次调用的时间
return function (...args) {
const now = Date.now(); // 当前时间
// 如果距离上次调用已经超过设定时间,则调用函数
if (now - lastTime > wait) {
lastTime = now; // 更新上一次调用的时间
fn.apply(this, args); // 以正确的`this`和参数调用函数
}
};
}
// 拿到的数据移除*
function filterString(str, charsToRemove) {
// 这里的正则表达式是通过将charsToRemove数组中的字符转换为字符类character class来构建的
@ -723,15 +735,15 @@
demoData = {
bloodGlucose: "血糖",
SleepDatas: "睡眠",
bloodOxygen: "血氧",
bloodOxygen: ['血氧', '血氧饱和度'],
bloodPressure: '血压',
meiTuo: '梅脱',
pulseReat: '心率',
bodyTemperature: '体温',
ECGData: '心电图',
bloodLiquid: ['血脂', '血液', '尿酸'],
bloodLiquid: ['血脂', '血液', '尿酸', '胆固醇', '甘油三脂', '高密度脂蛋白', '低密度脂蛋白'],
bodyData: '身体成分',
stepIndex: ['运动', '步数']
stepIndex: ['运动', '步数']
};
}
@ -742,16 +754,22 @@
const day = today.getDate();
// 初始化日期为今天
let targetDate = new Date(year, month, day);
let targetDate = new Date(year, month - 1, day);
// 检查时间词并设置目标日期
if (query.includes("昨天")) {
targetDate.setDate(day - 1);
} else if (query.includes("前天")) {
targetDate.setDate(day - 2);
}
const formattedDate = `${targetDate.getFullYear()}-${('0' + targetDate.getMonth()).slice(-2)}-${('0' + targetDate.getDate()).slice(-2)}`;
let offsetDays = 0; // 用于存储需要偏移的天数
if (query.includes("昨天")) {
offsetDays = -1;
} else if (query.includes("前天")) {
offsetDays = -2;
}
// 应用天数偏移,并正确处理跨月或跨年情况
targetDate.setDate(targetDate.getDate() + offsetDays);
// 格式化日期,确保月份和日期都是两位数
const formattedDate = `${targetDate.getFullYear()}-${String(targetDate.getMonth() + 1).padStart(2, '0')}-${String(targetDate.getDate()).padStart(2, '0')}`;
// 创建一个辅助函数来检查 bloodLiquid 对象是否包含查询字符串
function isBloodLiquidMatch(bloodLiquidData, query) {
@ -760,7 +778,7 @@
// 在查询逻辑中使用这个辅助函数
for (let key in demoData) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' ) {
if (typeof demoData[key] === 'object' && key === 'bloodLiquid' || typeof demoData[key] === 'object' && key === 'stepIndex' || typeof demoData[key] === 'object' && key === 'bloodOxygen' ) {
if (isBloodLiquidMatch(demoData[key], query)) {
key === 'stepIndex'? key = 'step_split' : ''; // 修改步数参数
return {
@ -773,13 +791,18 @@
dataKey: key,
date: formattedDate
};
}
} else if (pinyin(query, { toneType: 'none' }).replace(/\s/g, '').includes("xueyang")) { // 不容易识别转拼音,上面其实都可以优化
return {
dataKey: 'bloodOxygen',
date: formattedDate
};
}
}
// 如果没有找到匹配的数据项则返回null或错误信息这里选择返回null
return null;
}
}
};
</script>
@ -812,6 +835,30 @@
border-radius: 10px;
}
#shadow {
position: fixed;
z-index: 99999;
width: 100%;
height: 100vh;
left: 0;
top: 0;
background-color: #06193a;
}
#shadow-text {
width: 100%;
height: 100vh;
position: absolute;
text-align: center;
line-height: 100vh;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0 auto;
color: #fff;
}
#myVideo {
width: 100%;
height: 100% !important;

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -110,6 +110,7 @@
};
// 连接WebSocket
connectWebSocket() {
console.log('连接WebSocket')
return this.getWebSocketUrl().then(url => {
let iatWS;
if ('WebSocket' in window) {
@ -122,8 +123,11 @@
}
this.webSocket = iatWS;
this.setStatus('init');
iatWS.onopen = e => {
this.setStatus('ing');
console.log('ws开启重新开始录音');
// 重新开始录音
setTimeout(() => {
this.webSocketSend();
@ -140,6 +144,18 @@
};
})
};
// 防抖函数
debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
// 初始化浏览器录音
recorderInit() {
// 创建音频环境
@ -216,9 +232,10 @@
};
// 向webSocket发送数据(音频二进制数据经过Base64处理)
webSocketSend() {
console.log('发送数据')
if (this.webSocket.readyState !== 1) return false;
// 音频数据
const audioData = this.audioData.splice(0, 1280);
let audioData = this.audioData.splice(0, 1280);
const params = {
common: {
app_id: this.appId,
@ -237,14 +254,17 @@
audio: this.toBase64(audioData)
}
};
console.log(params, 'socket数据');
// 发送数据
this.webSocket.send(JSON.stringify(params));
this.handlerInterval = setInterval(() => {
// websocket未连接
if (this.webSocket.readyState !== 1) {
this.audioData = [];
clearInterval(this.handlerInterval);
return false;
return false;
};
if (this.audioData.length === 0) {
if (this.status === 'end') {
@ -312,9 +332,10 @@
this.webSocket.close();
}
};
// 启动录音
recorderStart() {
if (!this.audioContext) {
if (!this.audioContext) {
this.recorderInit();
} else {
this.audioContext.resume();
@ -340,8 +361,10 @@
this.setResultText({ resultText: '', resultTextTemp: '' });
};
// 停止
stop() {
stop() {
console.log('停了停了停了停了停了停了停了停了停了停了');
this.recorderStop();
this.webSocket.close();
};
};
}));

View File

@ -1 +1 @@
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__24DA8DD","name":"中鼎云医","version":{"name":"1.2.5","code":125},"description":"中鼎云医","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"VideoPlayer":{},"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"screenOrientation":"portrait","icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.15","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"},"screenOrientation":["portrait-primary","portrait-secondary"]}
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__24DA8DD","name":"中鼎云医","version":{"name":"1.2.8","code":128},"description":"中鼎云医","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"VideoPlayer":{},"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"compatible":{"ignoreVersion":true},"distribute":{"icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.36","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.