阶段性处理
This commit is contained in:
parent
2331d694ad
commit
02373b97be
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 聊天界面展示https://www.bilibili.com/video/BV1hT4y1P75N?p=22 搭建1和2 -->
|
<!-- 聊天界面展示https://www.bilibili.com/video/BV1hT4y1P75N?p=22 搭建1和2 -->
|
||||||
<view class="content">
|
<view class="content" @click="clickContent">
|
||||||
<view class="top_po">
|
<view class="top_po">
|
||||||
<view class="" @click="goback()"><u-icon name="arrow-left" color="#fff" size="20"></u-icon></view>
|
<view class="" @click="goback()"><u-icon name="arrow-left" color="#fff" size="20"></u-icon></view>
|
||||||
<view style="display: flex;">
|
<view style="display: flex;">
|
||||||
@ -14,7 +14,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<!-- 聊天内容 -->
|
<!-- 聊天内容 -->
|
||||||
<scroll-view class="chat" scroll-y="true" scroll-with-animation="true" :scroll-into-view="scrollToView">
|
<scroll-view class="chat" scroll-y="true" scroll-with-animation="true" :scroll-into-view="scrollToView">
|
||||||
<view @click="show=!show" class="chat-main" :style="{paddingBottom:inputh+'px'}">
|
<view class="chat-main" :style="{paddingBottom:inputh+'px'}">
|
||||||
<view class="chat-ls" v-for="(item,index) in messagesList" :key="index" :id="'msg'+ index">
|
<view class="chat-ls" v-for="(item,index) in messagesList" :key="index" :id="'msg'+ index">
|
||||||
<view class="msg-m msg-right">
|
<view class="msg-m msg-right">
|
||||||
<image class="user-img" :src="imagesUrl+userAvatar"></image>
|
<image class="user-img" :src="imagesUrl+userAvatar"></image>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<text>{{item.query}}</text>
|
<text>{{item.query}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="message" v-if="item.inputs.type == 'image'" @tap="previewImg(item.query)">
|
<view class="message" v-if="item.inputs.type == 'image'" >
|
||||||
<!-- 图像 -->
|
<!-- 图像 -->
|
||||||
<image :src="item.query" class="msg-img" mode="widthFix"></image>
|
<image :src="item.query" class="msg-img" mode="widthFix"></image>
|
||||||
</view>
|
</view>
|
||||||
@ -36,17 +36,19 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="msg-m msg-left" @click="clickSprink()" @touchstart="touchstart" @touchend="touchend" v-if="item.answer">
|
<view class="msg-m msg-left" v-if="item.answer">
|
||||||
|
|
||||||
<image class="user-img" :src="info.icon"></image>
|
<image class="user-img" :src="info.icon"></image>
|
||||||
<view class="msg-text" v-if="item.inputs.type == 'image'">
|
<view class="msg-text" v-if="item.inputs.type == 'image'">
|
||||||
<image :src="item.answer" class="msg-img" mode="widthFix"></image>
|
<image :src="item.answer" class="msg-img" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="msg-text" @click="clickSprink(index)" id="po_" v-else>
|
||||||
|
<view class="po_z" v-if="show=='1'&&clickIdx==index">
|
||||||
|
<view class="size_" @click="voiceTxt(item.answer)">Voice</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<view class="msg-text" id="po_" v-else>
|
{{item.answer}}</view>
|
||||||
<view class="po_z" v-if="show">
|
|
||||||
<view class="size_">Voice</view>
|
|
||||||
<view class="size_">text </view>
|
|
||||||
</view> {{item.answer}}</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<span id="bottomId"></span>
|
<span id="bottomId"></span>
|
||||||
@ -70,6 +72,7 @@
|
|||||||
} from './msgSocket'
|
} from './msgSocket'
|
||||||
import requestChat from '../../utils/requestChat'
|
import requestChat from '../../utils/requestChat'
|
||||||
import permision from "@/js_sdk/wa-permission/permission.js"
|
import permision from "@/js_sdk/wa-permission/permission.js"
|
||||||
|
import request from '../../utils/request'
|
||||||
//音频播放
|
//音频播放
|
||||||
const innerAudioContext = uni.createInnerAudioContext();
|
const innerAudioContext = uni.createInnerAudioContext();
|
||||||
// 录音
|
// 录音
|
||||||
@ -77,10 +80,11 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
audioSrc: '', // 用于存储音频的 URL
|
||||||
|
clickIdx:null,
|
||||||
//是否长按事件
|
//是否长按事件
|
||||||
islongPress:false,
|
|
||||||
timer:null,//长按计时器
|
timer:null,//长按计时器
|
||||||
show:false,
|
show:'0',
|
||||||
columns: [
|
columns: [
|
||||||
['Arabic-阿拉伯语',
|
['Arabic-阿拉伯语',
|
||||||
'German-德语',
|
'German-德语',
|
||||||
@ -146,40 +150,45 @@
|
|||||||
submit,
|
submit,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
longpress(){
|
async voiceTxt(text){
|
||||||
this.islongPress = true;
|
let res = await request({
|
||||||
this.show = true
|
url: 'youDaoApi/tts',
|
||||||
console.log("长按事件");
|
method: 'post',
|
||||||
},
|
data: {
|
||||||
//点击事件
|
q: text,
|
||||||
clickSprink(){
|
voiceName: this.lang ,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.playBase64Mp3(res.data)
|
||||||
|
this.show = false
|
||||||
|
|
||||||
|
},
|
||||||
|
// 播放 base64 编码的 MP3 文件
|
||||||
|
playBase64Mp3(base64Data) {
|
||||||
|
innerAudioContext.src = config.baseUrl+base64Data; // 不推荐,仅用于演示
|
||||||
|
innerAudioContext.play();
|
||||||
|
// 注意:如果你使用的是音频组件,确保在模板中正确绑定和使用它
|
||||||
|
},
|
||||||
|
clickContent(index){
|
||||||
|
if(this.info.conversation=='Translator'){
|
||||||
|
// 非长按
|
||||||
|
this.show = '0'
|
||||||
|
this.clickIdx = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//点击事件
|
||||||
|
clickSprink(index){
|
||||||
|
if(this.info.conversation=='Translator'){
|
||||||
// 非长按
|
// 非长按
|
||||||
if(this.islongPress == false){
|
|
||||||
console.log("点击事件");
|
|
||||||
}else if(this.islongPress == true){
|
|
||||||
|
|
||||||
|
|
||||||
console.log("长按事件",this.show);
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
//手指触摸动作开始
|
|
||||||
touchstart(){
|
|
||||||
this.timer = setTimeout(()=>{
|
|
||||||
this.longpress();
|
|
||||||
},1000)
|
|
||||||
},
|
|
||||||
//手指触摸动作结束
|
|
||||||
touchend(){
|
|
||||||
//延时执行为了防止 click() 还未判断 islongPress 的值就被置为 fasle
|
|
||||||
clearTimeout(this.timer);
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.islongPress = false
|
this.show = '1'
|
||||||
}, 200)
|
this.clickIdx = index
|
||||||
},
|
}, 10); // 延时200毫秒,即0.2秒
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
// 回调参数为包含columnIndex、value、values
|
// 回调参数为包含columnIndex、value、values
|
||||||
langConfirm(e) {
|
langConfirm(e) {
|
||||||
console.log('confirm', e)
|
|
||||||
this.lang = e.value[0].split('-')[0]
|
this.lang = e.value[0].split('-')[0]
|
||||||
this.langShow = false
|
this.langShow = false
|
||||||
},
|
},
|
||||||
@ -221,7 +230,6 @@
|
|||||||
this.goBottom()
|
this.goBottom()
|
||||||
uni.setStorageSync(this.storeList + '_' + this.info.conversation, this.messagesList)
|
uni.setStorageSync(this.storeList + '_' + this.info.conversation, this.messagesList)
|
||||||
}else{
|
}else{
|
||||||
console.log('触发首页的消息回调', res);
|
|
||||||
if (res.data.indexOf("conversation_id") > -1) {
|
if (res.data.indexOf("conversation_id") > -1) {
|
||||||
uni.setStorageSync(this.info.conversation, JSON.parse(res.data).conversation_id);
|
uni.setStorageSync(this.info.conversation, JSON.parse(res.data).conversation_id);
|
||||||
} else if (res.data.indexOf("workflow_finished") > -1) {
|
} else if (res.data.indexOf("workflow_finished") > -1) {
|
||||||
@ -241,10 +249,6 @@
|
|||||||
},
|
},
|
||||||
//缓存中获取历史消息
|
//缓存中获取历史消息
|
||||||
getMessageByStore() {
|
getMessageByStore() {
|
||||||
if (!uni.getStorageSync(this.info.conversation)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tempList = uni.getStorageSync(this.storeList + '_' + this.info.conversation)||[]
|
let tempList = uni.getStorageSync(this.storeList + '_' + this.info.conversation)||[]
|
||||||
if (tempList && tempList.length > 30) {
|
if (tempList && tempList.length > 30) {
|
||||||
//截取最新的30条
|
//截取最新的30条
|
||||||
|
@ -2,38 +2,40 @@
|
|||||||
<view class="container">
|
<view class="container">
|
||||||
<map id="map" :show-compass="true" :include-points="points" :polyline="polyline" lang="en" :longitude="center.longitude" :latitude="center.latitude"
|
<map id="map" :show-compass="true" :include-points="points" :polyline="polyline" lang="en" :longitude="center.longitude" :latitude="center.latitude"
|
||||||
:markers="markers" bindmarkertap="handleMarkerTap" show-location
|
:markers="markers" bindmarkertap="handleMarkerTap" show-location
|
||||||
:style="'width:' + windowWidth + 'px;' + 'height:'+ windowHeight+'px;' ">
|
:style="'width:' + windowWidth + 'px;' + 'height:'+ '540rpx;' ">
|
||||||
|
|
||||||
</map>
|
</map>
|
||||||
<view class="contenr_">
|
<image src="/static/chatImg/fy.png" @click="changeLan" mode="" class="fy_icon" ></image>
|
||||||
|
<view class="contenr_" v-if="lang=='en'" >
|
||||||
<view class="contenr_top">
|
<view class="contenr_top">
|
||||||
<!-- 顶部 全程 时间-->
|
<!-- 顶部 全程 时间-->
|
||||||
<view class="c_t_box">
|
<view class="c_t_box">
|
||||||
<view>
|
<view>
|
||||||
<text class="text_1">1 h22min</text>
|
<text class="text_1">{{Number.parseInt(allData.duration/60)||0}}min</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="ds_">
|
<view class="ds_">
|
||||||
<text class="text_2">Arrival time</text>
|
<text class="text_2">walk distance</text>
|
||||||
<text class="text_1">1 h22min</text>
|
<text class="text_1">{{allData.walkingDistance?Number.parseFloat(allData.walkingDistance/1000).toFixed(2):0}}km</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<view class="c_c_box">
|
<view class="c_c_box">
|
||||||
<view class="">
|
|
||||||
<image src="/static/imgs/icon1.png" style="height: 40rpx;width: 32rpx;margin-left: 8rpx;margin-bottom: 5rpx;"></image>
|
<view class="ds_" style="flex-wrap: wrap;">
|
||||||
</view>
|
|
||||||
<view class="ds_">
|
|
||||||
<image src="/static/imgs/icon2.png" style="height: 48rpx;width: 48rpx;"></image>
|
<image src="/static/imgs/icon2.png" style="height: 48rpx;width: 48rpx;"></image>
|
||||||
<view class="c_c_title" :style="'background-color:' + colorList[index] " v-for="(item,index) in 2" :key="index" >
|
<view v-for="(item,index) in allData.segments">
|
||||||
<text class="text_3">Rail Transit Line 2</text>
|
<view class="c_c_title" :style="'background-color:' + colorList[index] " v-for="(it,idx) in item.bus" :key="idx" >
|
||||||
|
<text class="text_line">{{it.enName.split('(')[0]||''}}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 下方注释 -->
|
<!-- 下方注释 -->
|
||||||
<view class="ds_">
|
<view class="ds_">
|
||||||
<text class="text_4">Walk 805 meters</text>
|
<text class="text_4">all cost</text>
|
||||||
<text class="text_4">5$</text>
|
<text class="text_4">¥{{allData.cost=='[]'?0:allData.cost}}</text>
|
||||||
<text class="text_4">15 Stations</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y :show-scrollbar="false" @scrolltoupper="upper" @scrolltolower="lower"
|
<scroll-view scroll-y :show-scrollbar="false" @scrolltoupper="upper" @scrolltolower="lower"
|
||||||
@ -43,20 +45,107 @@
|
|||||||
<image src="/static/imgs/icon3.png" style="height: 40rpx;width: 40rpx;margin-right: 20rpx;"></image>
|
<image src="/static/imgs/icon3.png" style="height: 40rpx;width: 40rpx;margin-right: 20rpx;"></image>
|
||||||
<text class="text_1">My Location</text>
|
<text class="text_1">My Location</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="c_b_box">
|
</view>
|
||||||
|
<!-- -- 我需要把循环包在这 这两块一起循环 下面的循环不需要 -->
|
||||||
|
<view class="c_box" v-for="(item,index) in allData.segments" :key="index">
|
||||||
|
<view class="c_b_box" v-if="item.walking">
|
||||||
<view class="ds_">
|
<view class="ds_">
|
||||||
<view class="qiu_"></view>
|
<view class="qiu_"></view>
|
||||||
<text class="text_4">Walk 621 meters (9 minutes)</text>
|
<text class="text_4">Walk {{item.walking.distance}} meters ({{Number.parseInt(item.walking.duration/60)}} minutes)</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="b_walk">
|
<view class="b_walk">
|
||||||
<text class="text_3">Walk</text>
|
<text class="text_3" @click="walkLine(item.walking)">Walk</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="contenr_bottom_d" v-if="item.bus&&item.bus.length>0" v-for="(it) in item.bus">
|
||||||
|
<view class="bz_left">
|
||||||
|
<view class="l_t_i" :style="'background-color:' + colorList[index] " >
|
||||||
|
<image src="/static/imgs/icon4.png" style="height: 32rpx;width: 32rpx;"></image>
|
||||||
|
</view>
|
||||||
|
<view class="l_t_z" :style="'background-color:' + colorList[index] " ></view>
|
||||||
|
<view class="l_t_i" :style="'background-color:' + colorList[index] "></view>
|
||||||
|
</view>
|
||||||
|
<view class="bz_right">
|
||||||
|
<text class="text_1" style="margin-bottom: 32rpx;">{{it.departureStop.enName}} station</text>
|
||||||
|
<view class="ds_">
|
||||||
|
<view class="bz_icon" :style="'background-color:' + colorList[index] ">
|
||||||
|
<text class="text_3">{{it.enName}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="botton_size">
|
||||||
|
<text class="text_4">{{it.viaStops.length}} station ({{Number.parseInt(it.duration/60)}} min)</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<text class="text_1" style="margin-top: 39rpx;">{{it.arrivalStop.enName}} station</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="contenr_bottom">
|
||||||
|
<view class="c_b_title">
|
||||||
|
<image src="/static/imgs/end.png" style="height: 50rpx;width: 45rpx;margin-right: 20rpx;"></image>
|
||||||
|
<text class="text_1">destination</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="contenr_" v-else >
|
||||||
|
<view class="contenr_top">
|
||||||
|
<!-- 顶部 全程 时间-->
|
||||||
|
<view class="c_t_box">
|
||||||
|
<view>
|
||||||
|
<text class="text_1">{{Number.parseInt(allData.duration/60)||0}}分钟</text>
|
||||||
|
</view>
|
||||||
|
<view class="ds_">
|
||||||
|
<text class="text_2">步行距离</text>
|
||||||
|
<text class="text_1">{{allData.walkingDistance?Number.parseFloat(allData.walkingDistance/1000).toFixed(2):0}}km</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- -->
|
||||||
|
<view class="c_c_box">
|
||||||
|
|
||||||
|
<view class="ds_" style="flex-wrap: wrap;">
|
||||||
|
<image src="/static/imgs/icon2.png" style="height: 48rpx;width: 48rpx;"></image>
|
||||||
|
<view v-for="(item,index) in allData.segments">
|
||||||
|
<view class="c_c_title" :style="'background-color:' + colorList[index] " v-for="(it,idx) in item.bus" :key="idx" >
|
||||||
|
<text class="text_line">{{it.name.split('(')[0]||''}}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 下方注释 -->
|
||||||
|
<view class="ds_">
|
||||||
|
<text class="text_4">总花费</text>
|
||||||
|
<text class="text_4">¥{{allData.cost}}</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<scroll-view scroll-y :show-scrollbar="false" @scrolltoupper="upper" @scrolltolower="lower"
|
||||||
|
:refresher-enabled="true" style="height: 620rpx;" lower-threshold="50">
|
||||||
|
<view class="contenr_bottom">
|
||||||
|
<view class="c_b_title">
|
||||||
|
<image src="/static/imgs/icon3.png" style="height: 40rpx;width: 40rpx;margin-right: 20rpx;"></image>
|
||||||
|
<text class="text_1">我的位置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- -- 我需要把循环包在这 这两块一起循环 下面的循环不需要 -->
|
||||||
|
<view class="c_box" v-for="(item,index) in allData.segments" :key="index">
|
||||||
|
<view class="c_b_box" v-if="item.walking">
|
||||||
|
<view class="ds_">
|
||||||
|
<view class="qiu_"></view>
|
||||||
|
<text class="text_4">步行 {{item.walking.distance}} 米 ({{Number.parseInt(item.walking.duration/60)}} 分钟)</text>
|
||||||
|
</view>
|
||||||
|
<view class="b_walk">
|
||||||
|
<text class="text_3" @click="walkLine(item.walking)">导航</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view v-for="(item,index) in 2" :key="index" class="contenr_bottom_d">
|
</view>
|
||||||
|
<view class="contenr_bottom_d" v-if="item.bus&&item.bus.length>0" v-for="(it) in item.bus">
|
||||||
<view class="bz_left">
|
<view class="bz_left">
|
||||||
<view class="l_t_i" :style="'background-color:' + colorList[index] " >
|
<view class="l_t_i" :style="'background-color:' + colorList[index] " >
|
||||||
<image src="/static/imgs/icon4.png" style="height: 32rpx;width: 32rpx;"></image>
|
<image src="/static/imgs/icon4.png" style="height: 32rpx;width: 32rpx;"></image>
|
||||||
@ -65,31 +154,31 @@
|
|||||||
<view class="l_t_i" :style="'background-color:' + colorList[index] "></view>
|
<view class="l_t_i" :style="'background-color:' + colorList[index] "></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="bz_right">
|
<view class="bz_right">
|
||||||
<text class="text_1" style="margin-bottom: 32rpx;">Zhudian Subway Station, Exit G</text>
|
<text class="text_1" style="margin-bottom: 32rpx;">{{it.departureStop.name}} 站点</text>
|
||||||
<view class="ds_">
|
<view class="ds_">
|
||||||
<view class="bz_icon" :style="'background-color:' + colorList[index] ">
|
<view class="bz_icon" :style="'background-color:' + colorList[index] ">
|
||||||
<text class="text_3">Line 2</text>
|
<text class="text_3">{{it.name}}</text>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<text class="text_5">Wangfuzhuang Direction</text>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="botton_size">
|
<view class="botton_size">
|
||||||
<text class="text_4">13 stops (33 min)</text>
|
<text class="text_4">{{it.viaStops.length}} 站 ({{Number.parseInt(it.duration/60)}} 分钟)</text>
|
||||||
<text class="text_4">上车站 首06.02 末23.47</text>
|
|
||||||
</view>
|
</view>
|
||||||
<text class="text_1" style="margin-top: 18rpx;">Wangfuzhuang Direction</text>
|
<text class="text_1" style="margin-top: 39rpx;">{{it.arrivalStop.name}} 站点</text>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="bottom_pr">
|
<view class="contenr_bottom">
|
||||||
<view class="button_">
|
<view class="c_b_title">
|
||||||
<text class="button_text">Start Navigation</text>
|
<image src="/static/imgs/end.png" style="height: 50rpx;width: 45rpx;margin-right: 20rpx;"></image>
|
||||||
|
<text class="text_1">终点</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -100,13 +189,16 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
lang:'en',
|
||||||
translateY: 0,
|
translateY: 0,
|
||||||
longPressTimer: null, // 长按定时器
|
longPressTimer: null, // 长按定时器
|
||||||
isDragging: false, // 是否正在拖动
|
isDragging: false, // 是否正在拖动
|
||||||
colorList:[
|
colorList:[
|
||||||
"#fcd803",
|
"#f9d402",
|
||||||
"#009bc2"
|
"#009bc2",
|
||||||
|
"#000000",
|
||||||
|
"#c34100",
|
||||||
|
"#006a00",
|
||||||
],
|
],
|
||||||
//打车预估路线
|
//打车预估路线
|
||||||
polyline: [],
|
polyline: [],
|
||||||
@ -126,7 +218,8 @@
|
|||||||
distance: 0,
|
distance: 0,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
cost:0,
|
cost:0,
|
||||||
points:[]
|
points:[],
|
||||||
|
allData:{}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -143,7 +236,7 @@
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return uni.getSystemInfoSync().windowHeight;
|
return uni.getSystemInfoSync().windowHeight/3;
|
||||||
},
|
},
|
||||||
windowWidth() {
|
windowWidth() {
|
||||||
return uni.getSystemInfoSync().windowWidth;
|
return uni.getSystemInfoSync().windowWidth;
|
||||||
@ -151,6 +244,37 @@
|
|||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
changeLan(){
|
||||||
|
if(this.lang == 'en'){
|
||||||
|
this.lang = 'zh'
|
||||||
|
}else{
|
||||||
|
this.lang = 'en'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
walkLine(data){
|
||||||
|
let endInfo = {}
|
||||||
|
endInfo.location = [data.endLocationLng, data.endLocationLat]
|
||||||
|
uni.getLocation({
|
||||||
|
// 谷歌使用wgs84 其他使用gcj02
|
||||||
|
type: 'gcj02', // 使用国测局坐标系
|
||||||
|
geocode: true,
|
||||||
|
success: function(res) {
|
||||||
|
let staInfo = {}
|
||||||
|
staInfo.location = [res.longitude, res.latitude]
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/PedestrianNavigation?startPoint=' + staInfo
|
||||||
|
.location +
|
||||||
|
'&endPoint=' + endInfo.location
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fail: function(err) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Failed to get location',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
upper(e) {
|
upper(e) {
|
||||||
console.log('Scroll to top');
|
console.log('Scroll to top');
|
||||||
},
|
},
|
||||||
@ -177,7 +301,7 @@
|
|||||||
endLocationLat: this.endPoint[1],
|
endLocationLat: this.endPoint[1],
|
||||||
}
|
}
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
that.allData = res.data
|
||||||
that.duration = res.data.duration/60
|
that.duration = res.data.duration/60
|
||||||
that.distance = res.data.walkingDistance/1000
|
that.distance = res.data.walkingDistance/1000
|
||||||
that.cost = res.data.cost
|
that.cost = res.data.cost
|
||||||
@ -252,7 +376,7 @@
|
|||||||
that.markers.push({
|
that.markers.push({
|
||||||
id:busIt.departureStop.id,
|
id:busIt.departureStop.id,
|
||||||
label:{
|
label:{
|
||||||
content:busIt.name,
|
content:busIt.enName,
|
||||||
fontSize:8,
|
fontSize:8,
|
||||||
color:'#145e07'
|
color:'#145e07'
|
||||||
},
|
},
|
||||||
@ -391,8 +515,9 @@
|
|||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
}
|
}
|
||||||
.bz_icon{
|
.bz_icon{
|
||||||
width: 100rpx;
|
box-sizing: border-box;
|
||||||
height: 40rpx;
|
padding: 18rpx 18rpx;
|
||||||
|
|
||||||
|
|
||||||
border-radius: 8rpx ;
|
border-radius: 8rpx ;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -430,7 +555,7 @@
|
|||||||
margin-right: 32rpx;
|
margin-right: 32rpx;
|
||||||
}
|
}
|
||||||
.c_b_box{
|
.c_b_box{
|
||||||
margin: 28rpx 0rpx;
|
margin: 10rpx 0rpx;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -447,7 +572,7 @@
|
|||||||
.contenr_{
|
.contenr_{
|
||||||
min-height: 160rpx;
|
min-height: 160rpx;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 160rpx;
|
bottom: 0rpx;
|
||||||
width: 750rpx;
|
width: 750rpx;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
@ -474,6 +599,11 @@
|
|||||||
.c_c_box{
|
.c_c_box{
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
}
|
}
|
||||||
|
.c_box{
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0px 32rpx;
|
||||||
|
|
||||||
|
}
|
||||||
.text_1{
|
.text_1{
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
@ -489,6 +619,11 @@
|
|||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
.text_line{
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 23rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
.text_4{
|
.text_4{
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
@ -503,7 +638,7 @@
|
|||||||
}
|
}
|
||||||
.c_c_title{
|
.c_c_title{
|
||||||
|
|
||||||
width: 280rpx;
|
width: 260rpx;
|
||||||
height: 48rpx;
|
height: 48rpx;
|
||||||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||||||
background: #fcd702;
|
background: #fcd702;
|
||||||
@ -513,7 +648,7 @@
|
|||||||
margin: 0px 5rpx;
|
margin: 0px 5rpx;
|
||||||
}
|
}
|
||||||
.contenr_bottom{
|
.contenr_bottom{
|
||||||
margin-top: 40rpx;
|
// margin-top: 40rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 32rpx;
|
padding: 32rpx;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
@ -521,7 +656,7 @@
|
|||||||
}
|
}
|
||||||
.contenr_bottom_d{
|
.contenr_bottom_d{
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 32rpx;
|
padding: 11rpx;
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
@ -561,4 +696,26 @@
|
|||||||
.botton_size{
|
.botton_size{
|
||||||
margin-top: 100rpx;
|
margin-top: 100rpx;
|
||||||
}
|
}
|
||||||
|
.fy_icon{
|
||||||
|
position: fixed;
|
||||||
|
right: 15px;
|
||||||
|
top: 15px;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
}
|
||||||
|
::v-deep .amap-logo {
|
||||||
|
opacity: 0 !important;
|
||||||
|
}
|
||||||
|
::v-deep .amap-copyright {
|
||||||
|
opacity: 0 !important;
|
||||||
|
}
|
||||||
|
::v-deep .BMap_cpyCtrl {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
::v-deep .anchorBL {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||||||
@Data
|
@Data
|
||||||
public class BusLinesResponse {
|
public class BusLinesResponse {
|
||||||
private String name; // 公交路线名称
|
private String name; // 公交路线名称
|
||||||
|
private String enName;
|
||||||
private String id; // 公交路线ID
|
private String id; // 公交路线ID
|
||||||
private String type; // 公交类型
|
private String type; // 公交类型
|
||||||
private int distance; // 行驶距离(米)
|
private int distance; // 行驶距离(米)
|
||||||
@ -27,6 +28,7 @@ public class BusLinesResponse {
|
|||||||
@Data
|
@Data
|
||||||
public static class DepartureStop {
|
public static class DepartureStop {
|
||||||
private String name;
|
private String name;
|
||||||
|
private String enName;
|
||||||
private String id;
|
private String id;
|
||||||
/**
|
/**
|
||||||
* 经度,不能为空
|
* 经度,不能为空
|
||||||
@ -43,6 +45,7 @@ public class BusLinesResponse {
|
|||||||
@Data
|
@Data
|
||||||
public static class ArrivalStop {
|
public static class ArrivalStop {
|
||||||
private String name;
|
private String name;
|
||||||
|
private String enName;
|
||||||
private String id;
|
private String id;
|
||||||
/**
|
/**
|
||||||
* 经度,不能为空
|
* 经度,不能为空
|
||||||
@ -59,6 +62,7 @@ public class BusLinesResponse {
|
|||||||
@Data
|
@Data
|
||||||
public static class ViaStop {
|
public static class ViaStop {
|
||||||
private String name;
|
private String name;
|
||||||
|
private String enName;
|
||||||
private String id;
|
private String id;
|
||||||
/**
|
/**
|
||||||
* 经度,不能为空
|
* 经度,不能为空
|
||||||
|
@ -6,14 +6,13 @@ import java.io.IOException;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.dc.app.controller.ChatApi;
|
import com.dc.app.controller.ChatApi;
|
||||||
|
import com.dc.system.mapper.SysConfigMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -22,11 +21,55 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static com.dc.system.until.AsrV2.*;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class ChatService {
|
public class ChatService {
|
||||||
@Resource
|
@Resource
|
||||||
private ChatApi chatApi;
|
private ChatApi chatApi;
|
||||||
|
@Resource
|
||||||
|
SysConfigMapper sysConfigMapper;
|
||||||
|
|
||||||
|
static Map<String, String> langMap = new HashMap<String, String>() {{
|
||||||
|
put("Arabic", "ar");
|
||||||
|
put("Bahasa (Indonesia)", "in");
|
||||||
|
put("Cantonese", "yue");
|
||||||
|
put("Catalan", "ca");
|
||||||
|
put("Czech", "cs");
|
||||||
|
put("Danish", "da");
|
||||||
|
put("Dutch", "nl");
|
||||||
|
put("Dutch (Belgium)", "nl-BEL");
|
||||||
|
put("English", "en");
|
||||||
|
put("Finnish", "fi");
|
||||||
|
put("French", "fr");
|
||||||
|
put("French (Canada)", "fr-CAN");
|
||||||
|
put("German", "de");
|
||||||
|
put("Greek", "el");
|
||||||
|
put("Hebrew", "he");
|
||||||
|
put("Hindi", "hi");
|
||||||
|
put("Hungarian", "hu");
|
||||||
|
put("Italian", "it");
|
||||||
|
put("Japanese", "ja");
|
||||||
|
put("Korean", "ko");
|
||||||
|
put("Mandarin (China)", "zh-CHS");
|
||||||
|
put("Mandarin (Taiwan)", "zh-TWN");
|
||||||
|
put("Norwegian", "no");
|
||||||
|
put("Polish", "pl");
|
||||||
|
put("Portuguese (Brazil)", "pt-BRA");
|
||||||
|
put("Portuguese (Portugal)", "pt");
|
||||||
|
put("Romanian", "ro");
|
||||||
|
put("Russian", "ru");
|
||||||
|
put("Slovak", "sk");
|
||||||
|
put("Spanish (Castilian)", "es-ESP");
|
||||||
|
put("Spanish (Columbia)", "es-COL");
|
||||||
|
put("Spanish (Mexico)", "es-MEX");
|
||||||
|
put("Spanish", "es"); // 修正重复项
|
||||||
|
put("Swedish", "sv");
|
||||||
|
put("Thai", "th");
|
||||||
|
put("Turkish", "tr");
|
||||||
|
}};
|
||||||
|
|
||||||
private static Map<String,String> sendFlagMap =new HashMap<>();
|
private static Map<String,String> sendFlagMap =new HashMap<>();
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<String, String> redisTemplate;
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
@ -40,6 +83,39 @@ public class ChatService {
|
|||||||
if (requestData.getJSONObject("inputs").getString("type").equals("image")||requestData.getJSONObject("inputs").getString("type").equals("voice")){
|
if (requestData.getJSONObject("inputs").getString("type").equals("image")||requestData.getJSONObject("inputs").getString("type").equals("voice")){
|
||||||
requestData.put("query",redisTemplate.opsForValue().get(requestData.getString("query")));
|
requestData.put("query",redisTemplate.opsForValue().get(requestData.getString("query")));
|
||||||
}
|
}
|
||||||
|
if (requestData.getJSONObject("inputs").getString("type").equals("voice")){
|
||||||
|
String appKey = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_KEY");
|
||||||
|
String appSecret = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_SECRET");
|
||||||
|
//如果是语言则直接走有道自己进行翻译 不需要走大模型
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
String langType = langMap.get(requestData.getJSONObject("inputs").getString("lang"));
|
||||||
|
params.put("appKey", appKey);
|
||||||
|
String q = requestData.getString("query");
|
||||||
|
params.put("q", q);
|
||||||
|
params.put("format", "wav");
|
||||||
|
params.put("rate", "16000");
|
||||||
|
params.put("channel", "1");
|
||||||
|
params.put("docType", "json");
|
||||||
|
params.put("type", "1");
|
||||||
|
String salt = UUID.randomUUID().toString();
|
||||||
|
params.put("salt", salt);
|
||||||
|
params.put("langType", langType);
|
||||||
|
String curtime = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
params.put("curtime", curtime);
|
||||||
|
String signStr = appKey + truncate(q) + salt + curtime + appSecret;
|
||||||
|
String sign = getDigest(signStr);
|
||||||
|
params.put("sign", sign);
|
||||||
|
params.put("signType", "v2");
|
||||||
|
JSONObject res = JSONObject.parseObject(doRequest("https://openapi.youdao.com/asrapi", params));
|
||||||
|
if(res.getString("errorCode").equals("0")){
|
||||||
|
JSONArray jsonArray = res.getJSONArray("result");
|
||||||
|
requestData.put("query",jsonArray.get(0));
|
||||||
|
JSONObject temp =new JSONObject();
|
||||||
|
temp.put("type","text");
|
||||||
|
requestData.put("inputs",temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
String url = "http://flintown.cn:8080/v1/chat-messages";
|
String url = "http://flintown.cn:8080/v1/chat-messages";
|
||||||
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
|
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
|
||||||
RequestBody body = RequestBody.create(mediaType, requestData.toJSONString());
|
RequestBody body = RequestBody.create(mediaType, requestData.toJSONString());
|
||||||
|
@ -2,10 +2,12 @@ package com.dc.system.controller;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.dc.common.core.domain.AjaxResult;
|
import com.dc.common.core.domain.AjaxResult;
|
||||||
|
import com.dc.system.domain.TtsRequest;
|
||||||
import com.dc.system.service.YoudaoService;
|
import com.dc.system.service.YoudaoService;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,5 +23,12 @@ public class YoudaoController {
|
|||||||
List<String> res = youdaoService.textOcr(params.getString("base64"));
|
List<String> res = youdaoService.textOcr(params.getString("base64"));
|
||||||
return AjaxResult.success(res);
|
return AjaxResult.success(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("tts")
|
||||||
|
public AjaxResult tts(@RequestBody TtsRequest ttsRequest, HttpServletResponse response) throws IOException, NoSuchAlgorithmException {
|
||||||
|
String res = youdaoService.tts(ttsRequest,response);
|
||||||
|
return AjaxResult.success("ok",res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.dc.system.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TtsRequest {
|
||||||
|
private String q;
|
||||||
|
private String voiceName;
|
||||||
|
}
|
@ -1,9 +1,16 @@
|
|||||||
package com.dc.system.service;
|
package com.dc.system.service;
|
||||||
|
|
||||||
|
import com.dc.system.domain.TtsRequest;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface YoudaoService {
|
public interface YoudaoService {
|
||||||
List<String> textOcr(String base64) throws NoSuchAlgorithmException, IOException;
|
List<String> textOcr(String base64) throws NoSuchAlgorithmException, IOException;
|
||||||
|
String tts(TtsRequest ttsRequest, HttpServletResponse response) throws IOException, NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -71,6 +68,40 @@ public class AmapServiceImpl implements AmapService {
|
|||||||
}
|
}
|
||||||
res.setSegments(segments);
|
res.setSegments(segments);
|
||||||
// 路线翻译
|
// 路线翻译
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
for (BusTransitResponse.Segment segment : res.getSegments()) {
|
||||||
|
List<BusLinesResponse> bus = segment.getBus();
|
||||||
|
for (BusLinesResponse busLinesResponse : bus) {
|
||||||
|
names.add(busLinesResponse.getName());
|
||||||
|
names.add(busLinesResponse.getDepartureStop().getName());
|
||||||
|
names.add(busLinesResponse.getArrivalStop().getName());
|
||||||
|
List<BusLinesResponse.ViaStop> viaStops = busLinesResponse.getViaStops();
|
||||||
|
for (BusLinesResponse.ViaStop viaStop : viaStops) {
|
||||||
|
names.add(viaStop.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用翻译接口逐个翻译每个字段
|
||||||
|
if (!names.isEmpty()) {
|
||||||
|
String translatedInstruction = mapAndFy.translateNames(names);
|
||||||
|
String tempStr = mapAndFy.extractTranslations(translatedInstruction);
|
||||||
|
List<String> tempList = Arrays.asList(tempStr.split("%&&"));
|
||||||
|
int i=0;
|
||||||
|
for (BusTransitResponse.Segment segment : res.getSegments()) {
|
||||||
|
List<BusLinesResponse> bus = segment.getBus();
|
||||||
|
for (BusLinesResponse busLinesResponse : bus) {
|
||||||
|
busLinesResponse.setEnName(tempList.get(i++));
|
||||||
|
busLinesResponse.getDepartureStop().setEnName(tempList.get(i++));
|
||||||
|
busLinesResponse.getArrivalStop().setEnName(tempList.get(i++));
|
||||||
|
List<BusLinesResponse.ViaStop> viaStops = busLinesResponse.getViaStops();
|
||||||
|
for (BusLinesResponse.ViaStop viaStop : viaStops) {
|
||||||
|
viaStop.setEnName(tempList.get(i++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
private AmapResponse dealWalk(JSONObject walking) throws Exception {
|
private AmapResponse dealWalk(JSONObject walking) throws Exception {
|
||||||
|
@ -3,22 +3,22 @@ package com.dc.system.service.impl;
|
|||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.dc.common.config.DCConfig;
|
||||||
import com.dc.common.utils.youdaoUtils.AuthV3Util;
|
import com.dc.common.utils.youdaoUtils.AuthV3Util;
|
||||||
|
import com.dc.common.utils.youdaoUtils.FileUtil;
|
||||||
|
import com.dc.system.domain.TtsRequest;
|
||||||
import com.dc.system.mapper.SysConfigMapper;
|
import com.dc.system.mapper.SysConfigMapper;
|
||||||
import com.dc.system.service.YoudaoService;
|
import com.dc.system.service.YoudaoService;
|
||||||
import org.apache.http.Header;
|
import com.dc.web.controller.tool.YOUDAOHttpUtil;
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.NameValuePair;
|
import java.io.File;
|
||||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
import java.nio.file.Files;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import java.nio.file.Paths;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import java.util.Base64;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClients;
|
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -27,10 +27,12 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static com.dc.system.until.OcrUtil.createRequestParams;
|
import static com.dc.system.until.OcrUtil.createRequestParams;
|
||||||
|
import static com.dc.system.until.OcrUtil.createTTSParams;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class YoudaoServiceServiceImpl implements YoudaoService {
|
public class YoudaoServiceServiceImpl implements YoudaoService {
|
||||||
private final String orcPath = "https://openapi.youdao.com/ocrapi";
|
private final String orcPath = "https://openapi.youdao.com/ocrapi";
|
||||||
|
private final String ttsPath = "https://openapi.youdao.com/ttsapi";
|
||||||
@Resource
|
@Resource
|
||||||
SysConfigMapper sysConfigMapper;
|
SysConfigMapper sysConfigMapper;
|
||||||
@Override
|
@Override
|
||||||
@ -58,5 +60,23 @@ public class YoudaoServiceServiceImpl implements YoudaoService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String tts(TtsRequest ttsRequest, HttpServletResponse response) throws IOException, NoSuchAlgorithmException {
|
||||||
|
ttsRequest.setVoiceName("youxiaomei");
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
String appKey = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_KEY");
|
||||||
|
String appSecret = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_SECRET");
|
||||||
|
// 添加请求参数
|
||||||
|
Map<String, String[]> params = createTTSParams(ttsRequest.getQ(), ttsRequest.getVoiceName());
|
||||||
|
// 添加鉴权相关参数
|
||||||
|
AuthV3Util.addTTSAuthParams(appKey, appSecret, params);
|
||||||
|
byte[] post = YOUDAOHttpUtil.doPost(ttsPath, null, params, "audio");
|
||||||
|
// 上传文件路径
|
||||||
|
String tempPath = java.util.UUID.randomUUID().toString().replace("-", "");
|
||||||
|
String filePath = DCConfig.getUploadPath()+File.separator+"tts"+File.separator +tempPath +".mp3";
|
||||||
|
FileUtil.saveFile(filePath, post, false);
|
||||||
|
return "profile/upload/tts"+File.separator +tempPath +".mp3";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
101
dc-Vue/dc-admin/src/main/java/com/dc/system/until/AsrV2.java
Normal file
101
dc-Vue/dc-admin/src/main/java/com/dc/system/until/AsrV2.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package com.dc.system.until;
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
public class AsrV2 {
|
||||||
|
public static String truncate(String q) {
|
||||||
|
if (q == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int len = q.length();
|
||||||
|
String result;
|
||||||
|
return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loadAsBase64(String filename) {
|
||||||
|
InputStream in = null;
|
||||||
|
byte[] data = null;
|
||||||
|
try {
|
||||||
|
in = new FileInputStream(filename);
|
||||||
|
data = new byte[in.available()];
|
||||||
|
in.read(data);
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return Base64.getEncoder().encodeToString(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String doRequest(String url, Map<String,String> requestParams) throws Exception{
|
||||||
|
String result = null;
|
||||||
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
for (String key : requestParams.keySet()) {
|
||||||
|
params.add(new BasicNameValuePair(key, requestParams.get(key)));
|
||||||
|
}
|
||||||
|
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
|
||||||
|
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
HttpEntity httpEntity = httpResponse.getEntity();
|
||||||
|
result = EntityUtils.toString(httpEntity, "utf-8");
|
||||||
|
EntityUtils.consume(httpEntity);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (httpResponse != null) {
|
||||||
|
httpResponse.close();
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
System.out.println("## release resouce error ##" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDigest(String string) {
|
||||||
|
if (string == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
byte[] btInput = string.getBytes(UTF_8);
|
||||||
|
try {
|
||||||
|
MessageDigest mdInst = MessageDigest.getInstance("SHA-256");
|
||||||
|
mdInst.update(btInput);
|
||||||
|
byte[] md = mdInst.digest();
|
||||||
|
int j = md.length;
|
||||||
|
char str[] = new char[j * 2];
|
||||||
|
int k = 0;
|
||||||
|
for (byte byte0 : md) {
|
||||||
|
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
|
||||||
|
str[k++] = hexDigits[byte0 & 0xf];
|
||||||
|
}
|
||||||
|
return new String(str);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
}
|
||||||
|
}
|
@ -31,4 +31,13 @@ public class OcrUtil {
|
|||||||
put("imageType", imageType);
|
put("imageType", imageType);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Map<String, String[]> createTTSParams(String q, String voiceName) throws IOException {
|
||||||
|
return new HashMap<String, String[]>() {{
|
||||||
|
put("q", new String[]{q});
|
||||||
|
put("voiceName", new String[]{voiceName} );
|
||||||
|
}};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
package com.dc.web.controller.tool;
|
||||||
|
|
||||||
|
import okhttp3.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class YOUDAOHttpUtil {
|
||||||
|
|
||||||
|
private static OkHttpClient httpClient = new OkHttpClient.Builder().build();
|
||||||
|
|
||||||
|
public static byte[] doGet(String url, Map<String, String[]> header, Map<String, String[]> params, String expectContentType) {
|
||||||
|
Request.Builder builder = new Request.Builder();
|
||||||
|
addHeader(builder, header);
|
||||||
|
addUrlParam(builder, url, params);
|
||||||
|
return requestExec(builder.build(), expectContentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] doPost(String url, Map<String, String[]> header, Map<String, String[]> body, String expectContentType) {
|
||||||
|
Request.Builder builder = new Request.Builder().url(url);
|
||||||
|
addHeader(builder, header);
|
||||||
|
addBodyParam(builder, body, "POST");
|
||||||
|
return requestExec(builder.build(), expectContentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addHeader(Request.Builder builder, Map<String, String[]> header) {
|
||||||
|
if (header == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String key : header.keySet()) {
|
||||||
|
String[] values = header.get(key);
|
||||||
|
if (values != null) {
|
||||||
|
for (String value : values) {
|
||||||
|
builder.addHeader(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addUrlParam(Request.Builder builder, String url, Map<String, String[]> params) {
|
||||||
|
if (params == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
|
||||||
|
for (String key : params.keySet()) {
|
||||||
|
String[] values = params.get(key);
|
||||||
|
if (values != null) {
|
||||||
|
for (String value : values) {
|
||||||
|
urlBuilder.addQueryParameter(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.url(urlBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addBodyParam(Request.Builder builder, Map<String, String[]> body, String method) {
|
||||||
|
if (body == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FormBody.Builder formBodyBuilder = new FormBody.Builder(StandardCharsets.UTF_8);
|
||||||
|
for (String key : body.keySet()) {
|
||||||
|
String[] values = body.get(key);
|
||||||
|
if (values != null) {
|
||||||
|
for (String value : values) {
|
||||||
|
formBodyBuilder.add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.method(method, formBodyBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] requestExec(Request request, String expectContentType) {
|
||||||
|
Objects.requireNonNull(request, "okHttp request is null");
|
||||||
|
|
||||||
|
try (Response response = httpClient.newCall(request).execute()) {
|
||||||
|
if (response.code() == 200) {
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
if (body != null) {
|
||||||
|
String contentType = response.header("Content-Type");
|
||||||
|
if (contentType != null && !contentType.contains(expectContentType)) {
|
||||||
|
String res = new String(body.bytes(), StandardCharsets.UTF_8);
|
||||||
|
System.out.println(res);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return body.bytes();
|
||||||
|
}
|
||||||
|
System.out.println("response body is null");
|
||||||
|
} else {
|
||||||
|
System.out.println("request failed, http code: " + response.code());
|
||||||
|
}
|
||||||
|
} catch (IOException ioException) {
|
||||||
|
System.out.println("request exec error: " + ioException.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package com.dc.common.utils.youdaoUtils;
|
package com.dc.common.utils.youdaoUtils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -21,7 +24,14 @@ public class AuthV3Util {
|
|||||||
*/
|
*/
|
||||||
public static void addAuthParams(String appKey, String appSecret, Map<String, Object> paramsMap)
|
public static void addAuthParams(String appKey, String appSecret, Map<String, Object> paramsMap)
|
||||||
throws NoSuchAlgorithmException {
|
throws NoSuchAlgorithmException {
|
||||||
String qArray = paramsMap.get("img").toString();
|
String qArray="";
|
||||||
|
if(ObjectUtil.isNotEmpty(paramsMap.get("q"))){
|
||||||
|
qArray = paramsMap.get("q").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(qArray)) {
|
||||||
|
qArray = paramsMap.get("img").toString();
|
||||||
|
}
|
||||||
String salt = UUID.randomUUID().toString();
|
String salt = UUID.randomUUID().toString();
|
||||||
String curtime = String.valueOf(System.currentTimeMillis() / 1000);
|
String curtime = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
String sign = calculateSign(appKey, appSecret, qArray, salt, curtime);
|
String sign = calculateSign(appKey, appSecret, qArray, salt, curtime);
|
||||||
@ -32,6 +42,26 @@ public class AuthV3Util {
|
|||||||
paramsMap.put("sign",sign);
|
paramsMap.put("sign",sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addTTSAuthParams(String appKey, String appSecret, Map<String, String[]> paramsMap)
|
||||||
|
throws NoSuchAlgorithmException {
|
||||||
|
String[] qArray = paramsMap.get("q");
|
||||||
|
if (qArray == null) {
|
||||||
|
qArray = paramsMap.get("img");
|
||||||
|
}
|
||||||
|
StringBuilder q = new StringBuilder();
|
||||||
|
for (String item : qArray) {
|
||||||
|
q.append(item);
|
||||||
|
}
|
||||||
|
String salt = UUID.randomUUID().toString();
|
||||||
|
String curtime = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
String sign = calculateSign(appKey, appSecret, q.toString(), salt, curtime);
|
||||||
|
paramsMap.put("appKey", new String[]{appKey});
|
||||||
|
paramsMap.put("salt", new String[]{salt});
|
||||||
|
paramsMap.put("curtime", new String[]{curtime});
|
||||||
|
paramsMap.put("signType", new String[]{"v3"});
|
||||||
|
paramsMap.put("sign", new String[]{sign});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算鉴权签名 -
|
* 计算鉴权签名 -
|
||||||
* 计算方式 : sign = sha256(appKey + input(q) + salt + curtime + appSecret)
|
* 计算方式 : sign = sha256(appKey + input(q) + salt + curtime + appSecret)
|
||||||
|
@ -21,9 +21,14 @@ public class FileUtil {
|
|||||||
|
|
||||||
public static String saveFile(String path, byte[] data, boolean needDecode) throws IOException {
|
public static String saveFile(String path, byte[] data, boolean needDecode) throws IOException {
|
||||||
File file = new File(path);
|
File file = new File(path);
|
||||||
if (!file.exists()) {
|
if (!file.exists())
|
||||||
file.createNewFile();
|
{
|
||||||
|
if (!file.getParentFile().exists())
|
||||||
|
{
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
file.createNewFile();
|
||||||
byte[] bytes = data;
|
byte[] bytes = data;
|
||||||
if (needDecode) {
|
if (needDecode) {
|
||||||
String base64 = new String(data, StandardCharsets.UTF_8);
|
String base64 = new String(data, StandardCharsets.UTF_8);
|
||||||
|
Loading…
Reference in New Issue
Block a user