Browse Source

todo listenVoice

voice
zmt 4 years ago
parent
commit
d8b0f277b2
  1. 6
      src/pages.json
  2. 4
      src/subpackage/device/js/device_api.js
  3. 849
      src/subpackage/device/pages/audio_manage/audio_manage.vue
  4. 3
      src/subpackage/device/pages/index/index.vue
  5. BIN
      src/subpackage/device/static/images/i_txt.png
  6. BIN
      src/subpackage/device/static/images/i_voice_1.png
  7. BIN
      src/subpackage/device/static/images/i_voice_2.png
  8. BIN
      src/subpackage/device/static/images/i_voice_3.png

6
src/pages.json

@ -242,6 +242,12 @@
"style" : {
"navigationBarTitleText": "咖啡机管理"
}
},
{
"path": "pages/audio_manage/audio_manage",
"style" : {
"navigationBarTitleText": "音响管理"
}
},
{
"path": "pages/coffee_test/coffee_test",

4
src/subpackage/device/js/device_api.js

@ -1,6 +1,7 @@
import { ORIGIN } from '../../../js/api';
export const DEVICE_API = {
ORIGIN:ORIGIN,
stadiumList:`${ORIGIN}/stadium/list`, // 店铺列表
vendingGoodsList:`${ORIGIN}/stadium/vending/goods/list`, // 售货柜-商品列表
vendingGoodsRestock:`${ORIGIN}/admin/stadium/vending/goods/restock`, // 售货柜-库存修改保存
@ -41,6 +42,9 @@ export const DEVICE_API = {
//2021/0507
organizeOrderDetail:`${ORIGIN}/assistant/gaPlayTogetherOrder/get`, //助手约玩订单详情
//2021/0705 音响
uploadAudio:`${ORIGIN}/upload/file/audio`, // 上传录音
sendAudio:`${ORIGIN}/ouxuanac/sendPacket`, // 发送上传录音并播放
}
export default DEVICE_API;

849
src/subpackage/device/pages/audio_manage/audio_manage.vue

@ -0,0 +1,849 @@
<template>
<view class="switch-manage">
<store-name></store-name>
<view class="sm-tit">
<text>{{pageInfo.name || '-'}}</text>
<text>{{pageInfo.tips || ''}}</text>
</view>
<view class="sm-list">
<view class="sl-item" v-for="(e, i) in deviceList" :key="i">
<view class="si-top">
<image mode="aspectFit" :src="getIcon()"></image>
<view class="st-right">
<view class="sr-name">{{e.hardware_name || '-'}}</view>
<!-- 门闸没有状态查询 -->
<!-- 请求接口自定义字段设备状态 1->在线0->离线 -->
<view class="sr-bot" v-if="pageInfo.id !=5">
<view :class="[e.defineStatusCode == 1?'active':'']">
<text>{{ e.defineStatusCode == 1 ? '设备在线' : e.defineStatusCode == 0?'设备离线' : '-' }}</text>
</view>
<image mode="aspectFit" src="/subpackage/device/static/images/refresh.png"
@click="refreshStatusBtn({switchInfo:e, index:i})"></image>
</view>
</view>
</view>
<block v-if="pageInfo.name=='音响管理'">
<view class="si-bottom">
<view v-if="pageInfo.isOpen" @click="operateBtn({ switchInfo: e, status: 1 })">
<image mode="aspectFit" :src="pageInfo.openIcon || ''"></image>
<view>{{pageInfo.openName || '-'}}</view>
</view>
<view v-if="pageInfo.isClose" @click="operateBtn({ switchInfo: e, status: 0 })">
<image mode="aspectFit" :src="pageInfo.closeIcon || ''"></image>
<view>{{pageInfo.closeName || '-'}}</view>
</view>
</view>
</block>
<!-- <block v-else>
<view class="si-bottom" v-if="pageInfo.isOpen || pageInfo.isClose">
<view v-if="pageInfo.isOpen" @click="operateBtn({ switchInfo: e, status: 1 })">
<image mode="aspectFit" :src="pageInfo.openIcon || ''"></image>
<view>{{pageInfo.openName || '-'}}</view>
</view>
<view v-if="pageInfo.isClose" @click="operateBtn({ switchInfo: e, status: 0 })">
<image mode="aspectFit" :src="pageInfo.closeIcon || ''"></image>
<view>{{pageInfo.closeName || '-'}}</view>
</view>
</view>
</block> -->
</view>
</view>
<!-- 音频控制 -->
<view class="voice_control_pad" v-if="voicePadConfig.showVoicePad">
<!-- 文字转语音 -->
<view class="cover_bg" @click.stop="voicePadConfig.showVoicePad=false">
</view>
<view class="v_box" v-if="voicePadConfig.step==0">
<textarea value="" v-model="voicePadConfig.txt" placeholder="请输您要说的话,输入标点符号,智能语音效果更好哦!" />
<view class="v_btns">
<view class="voice_btn btn_white" @click="sendVoice(voicePadConfig.txt)">发送</view>
<view class="voice_btn btn_green" @click="listenVoice(voicePadConfig.txt)">试听</view>
</view>
</view>
<!-- 录音 -->
<view class="v_box" v-else>
<view class="voice_title">请说话</view>
<image class="voice_img" src="../../static/images/i_voice.png" :src="getVoiceIcon(voicePadConfig.step)"
:class="voicePadConfig.step==2?'voice_img_playing':''"></image>
<view class="voice_btn " @longpress="longPressHandle" @touchend="touchEndHandle"
hover-class="btn_active" v-if="voicePadConfig.step<3">按住说话</view>
<!-- <view class="voice_btn btn_active" v-else-if="voicePadConfig.step==2">按住说话</view> -->
<!-- hover-class -->
<view class="v_btns" v-else-if="voicePadConfig.step==3">
<view class="voice_btn btn_white" @click="sendVoice()">发送</view>
<view class="voice_btn btn_green" @click="listenVoice()">听取录音</view>
</view>
</view>
</view>
</view>
</template>
<script>
const recorderManager = uni.getRecorderManager();
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
import store_name from '../../components/store_name/store_name';
import deviceServer from '../../js/device_server';
import deviceApi from '../../js/device_api';
const showArr = {
's14': {
id: 14,
name: '音响管理',
isOpen: true,
isClose: true,
openIcon: '/subpackage/device/static/images/i_txt.png',
closeIcon: '/subpackage/device/static/images/i_voice.png',
openName: '文转音',
closeName: '语音',
hardware_type: 'AudioPlayer',
tips: "点击对应音响的麦克风可以进行说话,说话内容将通过音响播放。",
},
}
import {
mapState
} from 'vuex';
import util from '../../../../utils/util';
export default {
components: {
'store-name': store_name
},
computed: {
...mapState({
curStoreInfo: state => state.device.curStoreInfo,
}),
getVoiceIcon() {
return i => {
return `../../static/images/i_voice_${i}.png`
}
},
},
watch: {
curStoreInfo(newVal, oldVal) {
this.deviceList = [];
this.getDeviceList({
stadium_id: newVal.id,
hardware_type: this.pageInfo.hardware_type
})
}
},
data() {
return {
pageInfo: {},
deviceList: [],
voicePadConfig: {
showVoicePad: true,
step: 1, // 0, 1 , 2 , 3
txt: "",
voicePath: "",
voiceUrl: "",
}
}
},
onLoad(options) {
let self = this;
recorderManager.onStop(function(res) {
console.log('recorder stop' + JSON.stringify(res));
self.voicePadConfig.voicePath = res.tempFilePath;
});
let _pageInfo = showArr[`s${options.sid}`] || {};
this.pageInfo = _pageInfo;
uni.setNavigationBarTitle({
title: _pageInfo.name
});
this.getDeviceList({
stadium_id: this.curStoreInfo.id,
hardware_type: _pageInfo.hardware_type
})
},
methods: {
longPressHandle(e) {
console.log("长按开始...");
this.voicePadConfig.step = 2
console.log('开始录音');
recorderManager.start({
format: "wav"
});
},
touchEndHandle(e) {
console.log("触摸结束...");
this.voicePadConfig.step = 3
console.log('录音结束');
recorderManager.stop();
},
//
HandleVoiceOperate({
switchInfo,
status
}) {
console.log(switchInfo, status);
if (status === 1) { //
console.log("文字转语音");
this.voicePadConfig.showVoicePad = true
this.voicePadConfig.step = 0
// this.voicePadConfig
} else { //
console.log("语音发送");
this.voicePadConfig.showVoicePad = true
this.voicePadConfig.step = 1
}
},
//
async sendVoice() {
let that = this
console.log(deviceApi.ORIGIN)
//
let _url = ""; //
if(this.voicePadConfig.step==0){
let txt = this.voicePadConfig.txt
_url = `${deviceApi.ORIGIN}/ouxuanac/tts/textToVoice.wav?text=${txt}&voice_type=4&speed=-1&volume=10`;
}
//
if(this.voicePadConfig.step==3){
console.log("88888",that.voicePadConfig.voicePath);
let e = await deviceServer.uploadFile({
url: deviceApi.uploadAudio,
filePath: that.voicePadConfig.voicePath
});
let _res = util.jsonPar(e.data);
if (_res.code == 0) {
console.log(123, _res)
that.voicePadConfig.voiceUrl = _res.data.url
console.log("上传成功:", that.voicePadConfig.voiceUrl);
_url = _res.data.url //
} else {
console.error('上传录音失败--->', _res);
util.showNone(_res.message || '上传录音失败,请重试!')
return
}
}
//data
let _data = {
"device": this.curStoreInfo.device_name,
"data": {
"name": "audio-player",
"value": {
"url": _url
}
},
"token": "f0d5c19b-b87e-11eb-bc7d-5254005df464"
}
//
this.operateReq({
data: _data
})
},
// TODO
async listenVoice() {
let txt = this.voicePadConfig.txt
console.log('播放录音', txt);
if(this.voicePadConfig.step==0){
//,
let url =`${deviceApi.ORIGIN}/ouxuanac/tts/textToVoice.wav?text=${txt}&voice_type=4&speed=-1&volume=10`;
let updated_url = await this.getDownloadUrl(url)
innerAudioContext.src = updated_url
}
if(this.voicePadConfig.step==3){
innerAudioContext.src = this.voicePadConfig.voicePath;
}
if(innerAudioContext.src)innerAudioContext.play();
},
//TODO
getDownloadUrl(url) {
console.log('下载录音');
return new Promise((rs,rj)=>{
})
return "下载录音"
},
getDeviceList({
stadium_id,
hardware_type,
limit = 100,
page = 1
}) {
util.showLoad();
deviceServer.get({
url: deviceApi.hardwareList,
data: {
'filter[hardware_type]': hardware_type,
'filter[stadium_id]': stadium_id,
'limit': limit,
'page': page,
},
failMsg: '加载失败!'
})
.then(res => {
util.hideLoad();
let _list = res.list || [];
this.deviceList = _list;
console.log(res)
})
.catch(util.hideLoad)
},
// status 0 -> 1 ->
operateBtn: util.debounce(function({
switchInfo,
status
}) {
if (switchInfo.hardware_type === "AudioPlayer") return this.HandleVoiceOperate({
switchInfo,
status
}); //0704
let _data = this.getOperateReqData({
switchInfo,
status
})
//->& 20201224 5
if (switchInfo.hardware_type === 'AccessControl' && status == 1) {
this.operateReq({
data: this.getOperateReqData({
switchInfo,
status: 0
}),
isTip: false,
isLoad: false
});
}
this.operateReq({
data: _data
});
}, 300, 300),
//
getOperateReqData({
switchInfo,
status
}) {
let {
curStoreInfo
} = this;
let _query = switchInfo.hardware_type === 'GateControl' ?
this.getGateQuery({
switchInfo,
status
}) :
this.getSwitchQuery({
switchInfo,
status
});
let _data = {
device: curStoreInfo.device_name, // ,
data: _query, // src\subpackage\device\js\ouxuanac.md
};
//->& 20201224 5
if (switchInfo.hardware_type === 'AccessControl' && status == 0) _data['delay'] = '5';
return _data;
},
//
operateReq({
data,
isTip = true,
isLoad = true
}) {
let that = this
if (isLoad) util.showLoad();
deviceServer.post({
url: deviceApi.ouxuanac,
data: data,
isDefaultGet: false,
})
.then(res => {
if (isLoad) util.hideLoad();
if (res.data.code == 0) {
if (isTip) util.showNone(res.data.message || '操作成功!');
that.voicePadConfig.showVoicePad = false; //voicePad
} else {
if (isTip) util.showNone(res.data.message || '操作失败!');
}
})
.catch(err => {
if (isLoad) util.hideLoad()
})
},
// //
getGateQuery({
switchInfo,
status
}) {
let {
enter_id,
leave_id,
hardware_net_addr
} = switchInfo;
// ID |-> enter_id -> leave_id|
let _cid = status === 1 ? enter_id :
status === 0 ? leave_id : '';
return {
name: 'gate',
value: {
tcp: hardware_net_addr + '',
cid: _cid + ''
},
is_delay: true,
queue_group: 'gate'
}
},
//
refreshStatusBtn: util.debounce(function({
switchInfo,
index
}) {
this.getStatusReq({
data: this.getSwitchStatusQuery(switchInfo),
index,
})
}, 300, 300),
//
getStatusReq({
data,
index
}) {
let _deviceList = this.deviceList.slice();
util.showLoad();
deviceServer.post({
url: deviceApi.ouxuanac,
data: data,
isDefaultGet: false,
})
.then(res => {
util.hideLoad();
let _data = res.data || {};
console.log(this.changeLowerCase(_data.data))
if (_data.code == 504 || this.changeLowerCase(_data.data).indexOf('timeout') != -1) {
_deviceList[index]['defineStatusCode'] = 0;
} else if (_data.code == 0 && this.changeLowerCase(_data.data).indexOf('timeout') == -1) {
_deviceList[index]['defineStatusCode'] = 1;
} else {
util.showNone(_data.message || '操作失败!');
}
this.deviceList = _deviceList;
// if(res.data.code == 0){
// if(isTip)util.showNone(res.data.message || '');
// }else{
// if(isTip)util.showNone(res.data.message || '');
// }
})
.catch(util.hideLoad)
},
//
//
getSwitchStatusQuery(switchInfo) {
let {
curStoreInfo
} = this;
let {
hardware_connect_method,
hardware_type,
hardware_id,
node_id,
hardware_net_addr
} = switchInfo;
const _query = {
name: this.getStatusQueryName(switchInfo),
value: {
id: hardware_id + '',
} // value String
};
if (this.changeLowerCase(hardware_connect_method) === 'tcp') _query.value['tcp'] = hardware_net_addr + '';
let _flag = this.changeLowerCase(hardware_connect_method) === 'serialport485' || this.changeLowerCase(
hardware_connect_method) === 'tcp';
if (_flag) {
if (hardware_type === 'Air') { // key op
_query.value['op'] = 'status'
_query['name'] = this.getAirQueryName(switchInfo)
} else {
_query.value['p'] = node_id + ''; // id
// postData.value['o'] = this.getRelayStatus(status); //
}
}
return {
device: curStoreInfo.device_name, // ,
data: _query, // src\subpackage\device\js\ouxuanac.md
}
// this.getStatusReq({
// index,
// data: {
// device: curStoreInfo.device_name, // ,
// data: _query, // src\subpackage\device\js\ouxuanac.md
// }
// })
},
// switchInfo ->
// status -> 0 -> 1 ->
// src\subpackage\device\js\ouxuanac.md
// hardware_type === 'Air'
getSwitchQuery({
switchInfo,
status
}) {
let {
hardware_connect_method,
hardware_type,
hardware_id,
node_id,
hardware_net_addr
} = switchInfo;
const postData = {
name: this.getQueryName(switchInfo),
value: {
id: hardware_id + '',
} // value String
};
if (this.changeLowerCase(hardware_connect_method) === 'gpio') postData.value['status'] = this
.getRelayStatus(status);
// tcp hardware_net_addr
if (this.changeLowerCase(hardware_connect_method) === 'tcp') postData.value['tcp'] = hardware_net_addr +
'';
let _flag = this.changeLowerCase(hardware_connect_method) === 'serialport485' || this.changeLowerCase(
hardware_connect_method) === 'tcp';
if (_flag) {
if (hardware_type === 'Air') { // key op
postData.value['op'] = this.getAirRelayStatus(status);
postData['name'] = this.getAirQueryName(switchInfo)
} else {
//
postData.value['p'] = node_id + ''; // id
postData.value['o'] = this.getRelayStatus(status); //
}
}
return postData;
},
changeLowerCase(str) {
return str.toString().toLocaleLowerCase();
},
//
// Low = "low", //
// High = "high", //
getRelayStatus(status) {
return ['high', 'low'][status] || ''
},
//
// status = "status",
// on = "on",
// off = "off",
getAirRelayStatus(status) {
return ['off', 'on'][status] || ''
},
// name
getStatusQueryName(switchInfo) {
let {
hardware_connect_method
} = switchInfo;
let _obj = {
'Gpio': 'get-rpio', //
'SerialPort485': 'zzio404d-gpio-status',
'Tcp': 'zzio404d-gpio-status-tcp',
};
return _obj[hardware_connect_method] || ''
},
// name
getQueryName(switchInfo) {
let {
hardware_connect_method
} = switchInfo;
let _obj = {
'Gpio': 'set-rpio', //
'SerialPort485': 'zzio404d-gpio',
'Tcp': 'zzio404d-gpio-tcp',
};
return _obj[hardware_connect_method] || ''
},
// name
getAirQueryName(switchInfo) {
let {
hardware_connect_method,
hardware_model
} = switchInfo;
let _flag = this.changeLowerCase(hardware_connect_method) === 'tcp' && this.changeLowerCase(
hardware_model) === 'jianda';
if (_flag) return 'ray-air-rs-tcp';
let _obj = {
'acmelec': 'acmelec',
'zhongnan': 'zhongnan',
'jianda': 'ray-air-rs'
};
return _obj[this.changeLowerCase(hardware_model)] || '';
},
getIcon() {
let {
pageInfo
} = this;
if (!pageInfo.id) return '';
return `/subpackage/device/static/images/devices/${pageInfo.id}.png`
}
}
}
</script>
<style lang="scss">
@import '~style/public.scss';
.sm-tit {
padding-left: 40upx;
padding-top: 52upx;
padding-bottom: 30upx;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
text:first-child {
line-height: 60upx;
font-size: 44upx;
font-weight: 500;
color: #333;
}
text:last-child {
width: 466rpx;
color: #9C9C9F;
font-size: 24rpx;
}
}
.sm-list {
padding: 0 32upx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.sl-item {
margin-bottom: 30upx;
width: 328upx;
border-radius: 10upx;
background-color: #fff;
.si-top {
padding: 20upx 20upx 30upx;
display: flex;
flex-wrap: nowrap;
>image {
flex-shrink: 0;
flex-grow: 0;
margin-right: 20upx;
width: 80upx;
height: 80upx;
}
.st-right {
flex-grow: 1;
>.sr-name {
margin-bottom: 8upx;
line-height: 44upx;
font-size: 32upx;
color: #333;
@include textHide(1);
}
.sr-bot {
display: flex;
align-items: center;
>view {
margin-right: 8upx;
padding: 0 12upx;
font-size: 20upx;
line-height: 28upx;
border-radius: 28upx;
border: 2upx solid #9A9A9D;
color: #9A9A9D;
&::before {
content: '';
margin-right: 12upx;
margin-top: -4upx;
display: inline-block;
vertical-align: middle;
width: 8upx;
height: 8upx;
border-radius: 50%;
background-color: #9A9A9D;
}
&.active {
color: #333333;
&::before {
background-color: $themeColor;
}
}
}
>image {
flex-shrink: 0;
flex-grow: 0;
width: 32upx;
height: 32upx;
}
}
}
}
.si-bottom {
padding-top: 30upx;
padding-bottom: 30upx;
display: flex;
justify-content: center;
border-top: 2upx solid #F2F2F7;
>view {
flex-shrink: 0;
flex-grow: 0;
width: 50%;
>image {
display: block;
margin: 0 auto 20upx;
width: 100upx;
height: 100upx;
}
>view {
font-size: 24upx;
line-height: 34upx;
text-align: center;
color: #9a9a9d;
}
}
}
}
}
//
.voice_control_pad {
position: fixed;
top: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
z-index: 1;
.cover_bg {
position: fixed;
top: 0;
background: rgba($color: #000000, $alpha: .3);
z-index: 2;
width: 100%;
height: 100%;
}
.v_box {
z-index: 3;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
border-radius: 5rpx;
width: 620rpx;
height: 550rpx;
background-color: white;
textarea {
margin-top: 50rpx;
width: 560rpx;
height: 260rpx;
}
.voice_title {
max-width: 560rpx;
color: #1A1A1A;
font-size: 32rpx;
font-weight: 800;
margin-top: 68rpx;
}
.voice_img {
margin-top: 70rpx;
width: 100rpx;
height: 100rpx;
}
.voice_img_playing {
width: 206rpx;
height: 100rpx;
}
.voice_btn {
margin-top: 100rpx;
width: 392rpx;
height: 112rpx;
background: #009874;
border-radius: 5rpx;
text-align: center;
line-height: 112rpx;
color: white;
font-size: 32rpx;
}
.btn_active {
color: black;
background-color: rgba($color: #000000, $alpha: .4);
}
.btn_white {
width: 204rpx;
height: 88rpx;
background-color: white;
color: #009874;
border: 1rpx solid #009874;
line-height: 88rpx;
}
.btn_green {
width: 204rpx;
height: 88rpx;
background-color: #009874;
color: white;
line-height: 88rpx;
}
.v_btns {
width: 470rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
}
}
</style>

3
src/subpackage/device/pages/index/index.vue

@ -33,7 +33,7 @@ const tabArr = [
{id: 11, name: '水阀', path: `/pages/switch_manage/switch_manage`},
{id: 12, name: '互动设备', path: `/pages/switch_manage/switch_manage`},
{id: 13, name: '监控', path: ``},
{id: 14, name: '音响', path: ``},
{id: 14, name: '音响', path: `/pages/audio_manage/audio_manage`},
{id: 15, name: '机器人', path: ``},
];
export default {
@ -74,6 +74,7 @@ export default {
e.id == 9 ||  //
e.id == 10 ||  //
e.id == 11 ||  //
e.id == 14 ||  //
e.id == 7   //
)return util.routeTo(`${rootPage}${e.path}?sid=${e.id}`, 'nT');
util.showNone(`开发中!`);

BIN
src/subpackage/device/static/images/i_txt.png

After

Width: 200  |  Height: 200  |  Size: 11 KiB

BIN
src/subpackage/device/static/images/i_voice_1.png

After

Width: 200  |  Height: 200  |  Size: 9.9 KiB

BIN
src/subpackage/device/static/images/i_voice_2.png

After

Width: 103  |  Height: 50  |  Size: 2.9 KiB

BIN
src/subpackage/device/static/images/i_voice_3.png

After

Width: 102  |  Height: 100  |  Size: 2.4 KiB

Loading…
Cancel
Save