|
|
|
@ -4,8 +4,8 @@ |
|
|
|
|
title="智能客服" @clickLeft="back" /> |
|
|
|
|
|
|
|
|
|
<!-- --> |
|
|
|
|
<scroll-view id="scrollview" class="jqr_dig_scroll" scroll-y="true" :style="{height:style.contentViewHeight+'px'}" |
|
|
|
|
:scroll-with-animation="true" :scroll-top="scrollTop"> |
|
|
|
|
<scroll-view id="scrollview" class="jqr_dig_scroll" scroll-y="true" |
|
|
|
|
:style="{height:style.contentViewHeight+'px'}" :scroll-with-animation="true" :scroll-top="scrollTop"> |
|
|
|
|
<view id="msgview" class="user-box" :class="item.typestyle" v-for="(item,index) in messages" :key="index"> |
|
|
|
|
<view class="quanbao"> |
|
|
|
|
<image :src="item.headurl" class="jqr_dig_pic"></image> |
|
|
|
@ -13,13 +13,13 @@ |
|
|
|
|
<span>泉宝</span> |
|
|
|
|
<span>{{ item.time }}</span> |
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
</view> |
|
|
|
|
<view class="dig_column "> |
|
|
|
|
<view :class="item.contentstyle"> |
|
|
|
|
<view class="janw_link" v-for="(items,index) in item.content" :key="index"> |
|
|
|
|
<navigator class="janw_link" @tap="goToMsgDetail(items)" v-for="(items,i) in item.content" |
|
|
|
|
:key="i"> |
|
|
|
|
{{items.text}} |
|
|
|
|
</view> |
|
|
|
|
</navigator> |
|
|
|
|
<navigator @tap="getSelectMsg(item.search,item.bcode,item.page+1)" |
|
|
|
|
v-if="item.type == 'jiqiren' && item.content.length >= 7" class="dig_more"> |
|
|
|
|
查看更多 |
|
|
|
@ -45,8 +45,6 @@ |
|
|
|
|
<view class="w_33 half" @tap="showText()"> |
|
|
|
|
<image src="/subPageB/static/img/jqr_jpan.png" class="jqr_tol_pic"></image> |
|
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<view class="w_33 half" @tap="goToIndex()"> |
|
|
|
|
<image src="/subPageB/static/img/jqr_home.png" class="jqr_tol_pic"></image> |
|
|
|
|
</view> |
|
|
|
@ -61,9 +59,7 @@ |
|
|
|
|
</text> |
|
|
|
|
|
|
|
|
|
</scroll-view> |
|
|
|
|
|
|
|
|
|
<view class="dly_flex jpan_mode"> |
|
|
|
|
|
|
|
|
|
<view class="b_tol_ipt"> |
|
|
|
|
<input v-model="inputValue" type="text" focus placeholder="请输入" |
|
|
|
|
placeholder-style="color:#999; font-size:24rpx" class="ipt_jqr" /> |
|
|
|
@ -74,13 +70,17 @@ |
|
|
|
|
</view> |
|
|
|
|
</view> |
|
|
|
|
<!-- 语音模式 --> |
|
|
|
|
<!-- <view class="yuyin_mode"> |
|
|
|
|
<view class="dly_flex_c jqr_tol_box"> |
|
|
|
|
|
|
|
|
|
<view class="yuyin_mode"> |
|
|
|
|
<view class="dly_flex_c jqr_tol_box" @touchstart="touchstart" @touchend="touchend"> |
|
|
|
|
<image src="/subPageB/static/img/jqr_yuy.png" class="jqr_tol_pic_l"></image> |
|
|
|
|
|
|
|
|
|
</view> |
|
|
|
|
</view> --> |
|
|
|
|
</view> |
|
|
|
|
<view v-if="recordStart" class="audio-animation"> |
|
|
|
|
<view class="audio-wave"> |
|
|
|
|
<text class="audio-wave-text" v-for="item in 10" :style="{'animation-delay': `${item/10}s`}"></text> |
|
|
|
|
<view class="text">松开 发送</view> |
|
|
|
|
</view> |
|
|
|
|
</view> |
|
|
|
|
</view> |
|
|
|
|
</view> |
|
|
|
|
</template> |
|
|
|
@ -97,6 +97,8 @@ innerAudioContext.autoplay = true; |
|
|
|
|
}, |
|
|
|
|
data() { |
|
|
|
|
return { |
|
|
|
|
//公共路径 |
|
|
|
|
rootPath: this.$config.ROOTPATH, |
|
|
|
|
threebut: true, |
|
|
|
|
textbut: false, |
|
|
|
|
allConList: [], |
|
|
|
@ -112,16 +114,16 @@ innerAudioContext.autoplay = true; |
|
|
|
|
typestyle: "dly_flex left_dig m-item", |
|
|
|
|
time: this.$util.getCurrentTime3(), |
|
|
|
|
headurl: "/subPageB/static/img/jqr_jxw.png", |
|
|
|
|
content:[{text:"您好,我是您的智能小助手"}], |
|
|
|
|
content: [{ |
|
|
|
|
text: "您好,我是您的智能小助手" |
|
|
|
|
}], |
|
|
|
|
contentstyle: "jqr_box_txt dig_gd" |
|
|
|
|
}], |
|
|
|
|
inputValue: "", |
|
|
|
|
luyinstart: true, |
|
|
|
|
voicePath: "", |
|
|
|
|
max: 5000, // 录音最大时长,单位毫秒 |
|
|
|
|
frame: 50, // 执行绘画的频率,单位毫秒 |
|
|
|
|
longTag: false, // 判定长按和点击的标识 |
|
|
|
|
maxTiming: false, // 最长录音时间的定时器 |
|
|
|
|
messageType: 'voice', // text 发送文本;voice 发送语音 |
|
|
|
|
recordStart: false, |
|
|
|
|
draw: undefined, |
|
|
|
|
seconds: '00', |
|
|
|
|
ms: '00', |
|
|
|
@ -177,7 +179,9 @@ innerAudioContext.autoplay = true; |
|
|
|
|
typestyle: "dly_flex_c2 right_dig m-item me", |
|
|
|
|
time: this.$util.getCurrentTime3(), |
|
|
|
|
headurl: "", |
|
|
|
|
content:[{text:title}], |
|
|
|
|
content: [{ |
|
|
|
|
text: title |
|
|
|
|
}], |
|
|
|
|
contentstyle: "jqr_box" |
|
|
|
|
}) |
|
|
|
|
this.scrollToBottom(); |
|
|
|
@ -212,6 +216,7 @@ innerAudioContext.autoplay = true; |
|
|
|
|
} |
|
|
|
|
content.push(item); |
|
|
|
|
} |
|
|
|
|
this.$nextTick(()=>{ |
|
|
|
|
this.messages.push({ |
|
|
|
|
type: "jiqiren", |
|
|
|
|
typestyle: "dly_flex left_dig m-item", |
|
|
|
@ -223,10 +228,14 @@ innerAudioContext.autoplay = true; |
|
|
|
|
bcode: baseinfo, |
|
|
|
|
contentstyle: "jqr_box dig_gd" |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
this.scrollToBottom(); |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
goToMsgDetail: function(items) { |
|
|
|
|
|
|
|
|
|
console.log(items) |
|
|
|
|
if (items.type == "user") { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -237,114 +246,29 @@ innerAudioContext.autoplay = true; |
|
|
|
|
} |
|
|
|
|
if (items.bcode == "3302") { |
|
|
|
|
uni.navigateTo({ |
|
|
|
|
url: "/subPageA/food/fooddetial/fooddetial?fid=" + items.dataid + "&fareacode=" + items.region |
|
|
|
|
url: "/subPageA/food/fooddetial/fooddetial?fid=" + items.dataid + "&fareacode=" + items |
|
|
|
|
.region |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
if (items.bcode == "3303") { |
|
|
|
|
uni.navigateTo({ |
|
|
|
|
url: "/subPageA/method/methoddetail/methoddetail?guid="+items.dataid |
|
|
|
|
url: "/subPageA/method/methodDetail/methodDetail?guid=" + items.dataid |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
if (items.bcode == "3304") { |
|
|
|
|
uni.navigateTo({ |
|
|
|
|
url: "/pagesA/travelroute/travelroutedetail/travelroutedetail?id="+items.dataid |
|
|
|
|
url: "/subPageB/hotel/hoteldetail/hoteldetail?id=" + items.dataid + '®ion=' + items |
|
|
|
|
.region |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
if (items.bcode == "3305") { |
|
|
|
|
uni.navigateTo({ |
|
|
|
|
url: "/subPageB/hotel/hoteldetail/hoteldetail?id="+items.dataid |
|
|
|
|
url: "/subPageA/travelroute/travelroutedetail/travelroutedetail?id=" + items.dataid |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
/* start: function() { |
|
|
|
|
this.longTag = setTimeout(this.recording, 500); // 定义超过500ms即为长按,可自行修改 |
|
|
|
|
}, |
|
|
|
|
move: function() { |
|
|
|
|
clearTimeout(this.longTag); |
|
|
|
|
clearTimeout(this.maxTiming); |
|
|
|
|
clearInterval(this.draw); |
|
|
|
|
this.longTag = false; |
|
|
|
|
}, |
|
|
|
|
end: function() { |
|
|
|
|
clearTimeout(this.longTag); |
|
|
|
|
clearTimeout(this.maxTiming); |
|
|
|
|
clearInterval(this.draw); |
|
|
|
|
if (this.longTag) { // timeout不是false证明没有触发recording或者touchmove事件 |
|
|
|
|
console.log('按住时间少于500ms会执行这里并return'); |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
this.longTag = false; |
|
|
|
|
this.draw = false; |
|
|
|
|
if(this.yuyintype){ |
|
|
|
|
this.stopRecord(); |
|
|
|
|
} |
|
|
|
|
this.yuyintype = true; |
|
|
|
|
}, */ |
|
|
|
|
recording: function() { |
|
|
|
|
if(this.luyinstart){ |
|
|
|
|
uni.showLoading({ |
|
|
|
|
title: '录音中,再次点击结束录音' |
|
|
|
|
}); |
|
|
|
|
this.startRecord(); |
|
|
|
|
this.luyinstart = false; |
|
|
|
|
}else{ |
|
|
|
|
uni.hideLoading(); |
|
|
|
|
uni.showToast({ |
|
|
|
|
title: '结束录音', |
|
|
|
|
duration: 2000 |
|
|
|
|
}); |
|
|
|
|
this.stopRecord(); |
|
|
|
|
this.luyinstart = true; |
|
|
|
|
} |
|
|
|
|
/* // 开始录音 |
|
|
|
|
this.longTag = false; |
|
|
|
|
|
|
|
|
|
this.startRecord(); |
|
|
|
|
|
|
|
|
|
// 最大录音时间10秒 |
|
|
|
|
this.maxTiming = setTimeout(function() { |
|
|
|
|
//clearInterval(this.draw); |
|
|
|
|
self.stopRecord(); |
|
|
|
|
self.yuyintype = false; |
|
|
|
|
// 语音转换 |
|
|
|
|
// self.send(); |
|
|
|
|
}, self.max); */ |
|
|
|
|
|
|
|
|
|
// 录音过程圆圈动画 |
|
|
|
|
/*let angle = -0.5; |
|
|
|
|
let context = uni.createCanvasContext('canvas'); |
|
|
|
|
this.draw = setInterval(function() { |
|
|
|
|
context.beginPath(); |
|
|
|
|
context.setStrokeStyle("#11C966"); |
|
|
|
|
context.setLineWidth(3); |
|
|
|
|
context.arc(61,40, 35, -0.5 * Math.PI, (angle += 2 / (self.max / self.frame)) * Math.PI, false); |
|
|
|
|
context.stroke(); |
|
|
|
|
context.draw(); |
|
|
|
|
}, self.frame); */ |
|
|
|
|
}, |
|
|
|
|
//开始录音 |
|
|
|
|
startRecord:function() { |
|
|
|
|
let that = this; |
|
|
|
|
that.$wechat.startRecord( |
|
|
|
|
function(res){ |
|
|
|
|
console.log("开始录音") |
|
|
|
|
},function(res){ |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
//停止录音并识别文字 |
|
|
|
|
stopRecord:function(){ |
|
|
|
|
let that = this; |
|
|
|
|
that.$wechat.stopRecord( |
|
|
|
|
function(res){ |
|
|
|
|
var str = res.translateResult.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\,|\.|\<|\。|\>|\/|\?]/g,""); |
|
|
|
|
that.getMsg(str,'',1) |
|
|
|
|
},function(res){ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
) |
|
|
|
|
}, |
|
|
|
|
/** |
|
|
|
|
/** |
|
|
|
|
* @author gongliying |
|
|
|
|
* @date 2019-07-26 |
|
|
|
|
* @information 跳转页面底部 |
|
|
|
@ -356,16 +280,164 @@ innerAudioContext.autoplay = true; |
|
|
|
|
query.select('#scrollview').boundingClientRect(); |
|
|
|
|
query.exec((res) => { |
|
|
|
|
that.style.mitemHeight = 0; |
|
|
|
|
res[0].forEach((rect) => that.style.mitemHeight = that.style.mitemHeight + rect.height + 200) //获取所有内部子元素的高度 |
|
|
|
|
// 因为vue的虚拟DOM 每次生成的新消息都是之前的,所以采用异步setTimeout 主要就是添加了这定时器 |
|
|
|
|
setTimeout(() => { |
|
|
|
|
res[0].forEach((rect) => that.style.mitemHeight = that.style.mitemHeight + rect.height + |
|
|
|
|
200) //获取所有内部子元素的高度 |
|
|
|
|
// 因为vue的虚拟DOM 每次生成的新消息都是之前的,所以采用异步setTimeout 主要就是添加了这定时器 |
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
|
|
|
|
if (that.style.mitemHeight > (that.style.contentViewHeight - 100)) { //判断子元素高度是否大于显示高度 |
|
|
|
|
that.scrollTop = that.style.mitemHeight - that.style.contentViewHeight //用子元素的高度减去显示的高度就获益获得序言滚动的高度 |
|
|
|
|
} |
|
|
|
|
}, 100) |
|
|
|
|
}) |
|
|
|
|
if (that.style.mitemHeight > (that.style.contentViewHeight - |
|
|
|
|
100)) { //判断子元素高度是否大于显示高度 |
|
|
|
|
that.scrollTop = that.style.mitemHeight - that.style |
|
|
|
|
.contentViewHeight //用子元素的高度减去显示的高度就获益获得序言滚动的高度 |
|
|
|
|
} |
|
|
|
|
}, 100) |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
//开启麦克风权限 |
|
|
|
|
authTips() { |
|
|
|
|
uni.showModal({ |
|
|
|
|
title: '提示', |
|
|
|
|
content: '您拒绝了麦克风权限,将导致功能不能正常使用,去设置权限?', |
|
|
|
|
confirmText: '去设置', |
|
|
|
|
cancelText: '取消', |
|
|
|
|
success: (res) => { |
|
|
|
|
if (res.confirm) { |
|
|
|
|
uni.openSetting({ |
|
|
|
|
success: (res) => { |
|
|
|
|
if (res.authSetting['scope.record']) { |
|
|
|
|
console.log("已授权麦克风"); |
|
|
|
|
this._recordAuth = true |
|
|
|
|
} else { |
|
|
|
|
// 未授权 |
|
|
|
|
wx.showModal({ |
|
|
|
|
title: '提示', |
|
|
|
|
content: '您未授权麦克风,功能将无法使用', |
|
|
|
|
showCancel: false, |
|
|
|
|
confirmText: '知道了' |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
//开启录音 |
|
|
|
|
touchstart() { |
|
|
|
|
this.threebut = false; |
|
|
|
|
this.textbut = true; |
|
|
|
|
//开始录音 |
|
|
|
|
const _permission = 'scope.record' |
|
|
|
|
uni.getSetting({ |
|
|
|
|
success: (res) => { |
|
|
|
|
// 判断是否有相关权限属性 |
|
|
|
|
if (res.authSetting.hasOwnProperty(_permission)) { |
|
|
|
|
// 属性存在,且为false,用户拒绝过权限 |
|
|
|
|
if (!res.authSetting[_permission]) { |
|
|
|
|
this.authTips() |
|
|
|
|
} else { |
|
|
|
|
// 已授权 |
|
|
|
|
this._recordAuth = true |
|
|
|
|
// 开始录音 |
|
|
|
|
recorderManager.start({ |
|
|
|
|
format: 'pcm', |
|
|
|
|
}) |
|
|
|
|
recorderManager.onStart(() => { |
|
|
|
|
this.recordStart = true |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// 错误回调 |
|
|
|
|
recorderManager.onError((res) => { |
|
|
|
|
console.log('recorder error', res) |
|
|
|
|
uni.showToast({ |
|
|
|
|
icon: 'none', |
|
|
|
|
title: '系统出错,请重试' |
|
|
|
|
}) |
|
|
|
|
this.recordStart = false |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// 属性不存在,需要授权 |
|
|
|
|
uni.authorize({ |
|
|
|
|
scope: _permission, |
|
|
|
|
success: () => { |
|
|
|
|
// 授权成功 |
|
|
|
|
this._recordAuth = true |
|
|
|
|
}, |
|
|
|
|
fail: (res) => { |
|
|
|
|
/** |
|
|
|
|
* 104 未授权隐私协议 |
|
|
|
|
* 用户可能拒绝官方隐私授权弹窗,为了避免过度弹窗打扰用户,开发者再次调用隐私相关接口时, |
|
|
|
|
* 若距上次用户拒绝不足10秒,将不再触发弹窗,直接给到开发者用户拒绝隐私授权弹窗的报错 |
|
|
|
|
*/ |
|
|
|
|
if (res.errno == 104) { |
|
|
|
|
uni.showModal({ |
|
|
|
|
title: '温馨提示', |
|
|
|
|
content: '您拒绝了隐私协议,请稍后再试', |
|
|
|
|
confirmText: '知道了', |
|
|
|
|
showCancel: false, |
|
|
|
|
success: () => {} |
|
|
|
|
}) |
|
|
|
|
} else { |
|
|
|
|
// 用户拒绝授权 |
|
|
|
|
this.authTips() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
//停止录音 |
|
|
|
|
touchend() { |
|
|
|
|
const $this = this |
|
|
|
|
if (!this._recordAuth || !this.recordStart) return |
|
|
|
|
//停止录音 |
|
|
|
|
recorderManager.stop(); |
|
|
|
|
recorderManager.onStop((res) => { |
|
|
|
|
const { |
|
|
|
|
duration, |
|
|
|
|
tempFilePath |
|
|
|
|
} = res |
|
|
|
|
this.recordStart = false |
|
|
|
|
|
|
|
|
|
wx.uploadFile({ |
|
|
|
|
url: $this.rootPath + '/app-api/wechatshop/toolIdentify/identifySpeech', |
|
|
|
|
filePath: tempFilePath, |
|
|
|
|
name: 'file', |
|
|
|
|
formData: { |
|
|
|
|
'file': tempFilePath |
|
|
|
|
}, |
|
|
|
|
success: function(res) { |
|
|
|
|
let data = JSON.parse(res.data) |
|
|
|
|
|
|
|
|
|
$this.messages.push({ |
|
|
|
|
type: "user", |
|
|
|
|
typestyle: "dly_flex_c2 right_dig m-item me", |
|
|
|
|
time: $this.$util.getCurrentTime3(), |
|
|
|
|
headurl: "", |
|
|
|
|
content: [{ |
|
|
|
|
text: data.data |
|
|
|
|
}], |
|
|
|
|
contentstyle: "jqr_box" |
|
|
|
|
}) |
|
|
|
|
$this.getSelectMsg(data.data, "", 1); |
|
|
|
|
$this.scrollToBottom(); |
|
|
|
|
}, |
|
|
|
|
fail: function(res) { |
|
|
|
|
UTIL.log(res); |
|
|
|
|
wx.showModal({ |
|
|
|
|
title: '提示', |
|
|
|
|
content: "网络请求失败,请确保网络是否正常", |
|
|
|
|
showCancel: false, |
|
|
|
|
success: function(res) {} |
|
|
|
|
}); |
|
|
|
|
wx.hideToast(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
</script> |
|
|
|
@ -421,13 +493,16 @@ innerAudioContext.autoplay = true; |
|
|
|
|
padding-left: 20rpx |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.lazy_sech { |
|
|
|
|
background-color: #fff; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.jqr_tol { |
|
|
|
|
height: fit-content; |
|
|
|
|
padding: 20rpx 0 50rpx 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.jpan_mode { |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
@ -458,7 +533,56 @@ innerAudioContext.autoplay = true; |
|
|
|
|
.dig_more { |
|
|
|
|
bottom: 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.noPadding { |
|
|
|
|
padding-bottom: 20rpx !important; |
|
|
|
|
} |
|
|
|
|
.audio-animation { |
|
|
|
|
position: fixed; |
|
|
|
|
// width: 100vw; |
|
|
|
|
// height: 100vh; |
|
|
|
|
left: 50%; |
|
|
|
|
top: 50%; |
|
|
|
|
transform: translate(-50%, -50%); |
|
|
|
|
z-index: 202410; |
|
|
|
|
display: flex; |
|
|
|
|
justify-content: center; |
|
|
|
|
align-items: center; |
|
|
|
|
|
|
|
|
|
.text { |
|
|
|
|
text-align: center; |
|
|
|
|
font-size: 28rpx; |
|
|
|
|
color: #333; |
|
|
|
|
margin-top: 60rpx; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.audio-wave { |
|
|
|
|
padding: 50rpx; |
|
|
|
|
|
|
|
|
|
.audio-wave-text { |
|
|
|
|
background-color: #0983ff; |
|
|
|
|
width: 7rpx; |
|
|
|
|
height: 12rpx; |
|
|
|
|
margin: 0 6rpx; |
|
|
|
|
border-radius: 5rpx; |
|
|
|
|
display: inline-block; |
|
|
|
|
border: none; |
|
|
|
|
animation: wave 0.25s ease-in-out; |
|
|
|
|
animation-iteration-count: infinite; |
|
|
|
|
animation-direction: alternate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 声波动画 */ |
|
|
|
|
@keyframes wave { |
|
|
|
|
from { |
|
|
|
|
transform: scaleY(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
to { |
|
|
|
|
transform: scaleY(4); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
</style> |