<template>
	<view class="switch-manage">
		<store-name></store-name>
		<view class="sm-tit">
			<text>{{pageInfo.name || '-'}}</text>
			<text>{{pageInfo.tips || ''}}</text>
		</view>
		
		<view class="slider-box">
			<text>音量</text>
			<slider :value="voiceLevel" activeColor="#009874" block-color="#009874" block-size="22" @change="sliderChange" min="0" max="100" />
			<view class="">
				<text>0%</text>
				<text>100%</text>
			</view>
		</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>
			</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()">发送</view>
					<view class="voice_btn btn_green" @click="listenVoice()">试听</view>
				</view>
			</view>
			<!-- 录音 -->
			<view class="v_box" v-else>
				<view class="voice_title">{{getVoiceTxt(voicePadConfig.step)}}</view>
				<image class="voice_img" src="../../static/images/i_voice.png" :src="getVoiceIcon(voicePadConfig.step)"
					:class="voicePadConfig.step==2||voicePadConfig.step==4?'voice_img_playing':''"></image>
				<view class="voice_btn " @longpress="longPressHandle" @touchend="touchEndHandle"
					hover-class="btn_active" v-if="voicePadConfig.step<3">按住说话</view>
				<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>
	/**
	 * 20231129 
	 * fix 语音发送云中控参数 AC_filterCloudACData
	 * 新增 value.text
	 * 
	 * 
	 * */ 
	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';
	import { mapState } from 'vuex';
	import util from '../../../../utils/util';
	import DEVICE_FUN from '../../js/device_fun.js';

	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_1.png',
			openName: '文转音',
			closeName: '语音',
			hardware_type: 'AudioPlayer',
			tips: "点击对应音响的麦克风可以进行说话，说话内容将通过音响播放。",
		},
	}
	
	export default {
		components: {
			'store-name': store_name
		},
		computed: {
			...mapState({
				curStoreInfo: state => state.device.curStoreInfo,
			}),
			getVoiceIcon() {
				return i => {
					return `../../static/images/i_voice_${i}.png`
				}
			},
			getVoiceTxt() {
				return i => {
					return [,'请按住说话','录音中...','录音已完成','播放中...'][i]
				}
			},

		},
		watch: {
			curStoreInfo(newVal, oldVal) {
				this.deviceList = [];
				this.getDeviceList({
					stadium_id: newVal.id,
					hardware_type: this.pageInfo.hardware_type
				})
				
			},
		},
		data() {
			return {
				pageInfo: {},
				deviceList: [],
				voicePadConfig: {
					showVoicePad: false,
					step: 1, // 0 文字转语音, 1 未录音, 2 录音中, 3 录音结束, 4 播放录音中, 
					txt: "",
					voicePath: "",
					voiceUrl: "",
				},
				voiceLevel:0,

				// 20231129 fix 云中控判断
				curSwitch: null,
			}
		},
		onLoad(options) {
			this.initAudio();
			this.initPage(options);
			
		},
		methods: {
			//初始化音频
			initAudio(){
				let self = this;
				recorderManager.onStop(function(res) {
					console.log('recorder stop' + JSON.stringify(res));
					self.voicePadConfig.voicePath = res.tempFilePath;
				});
				innerAudioContext.onPlay(function(res) {
					console.log('play voice onPlay' + JSON.stringify(res));
					if(self.voicePadConfig.step==3)self.voicePadConfig.step = 4
				});
				innerAudioContext.onEnded(function(res) {
					console.log('play voice onEnded' + JSON.stringify(res));
					if(self.voicePadConfig.step == 4)self.voicePadConfig.step = 3
				});
			},
			initPage(options){
				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
				})
				this.updateVoiceSlider();
				
			},
			//滑动更改音响音量
			sliderChange(e) {
				console.log('value 发生变化：' + e.detail.value)
				let _data = {
					"device": this.curStoreInfo.device_name,
					"data": {
						"name": "audio-player-volume",
						"value": {
							"volume": e.detail.value.toString()
						}
					},	
				}
				//发送命令到中控
				this.operateReq({
					data: _data,
					isTip:true
				})
			},
			//更新音响音量
			updateVoiceSlider(){
				let that = this
				let _data = {
					"device": this.curStoreInfo.device_name,
					"data": {
						"name": "audio-player-volume",
						"value": {
							"volume": "-1"
						}
					},	
				}
				//发送命令到中控
				this.operateReq({
					data: _data,
					succFun: (res) => {
						console.log("操作结果:",res);
						that.voiceLevel = res.data
					},
					isTip:false
				})
			},
			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
				} 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
					if(!txt)return util.showNone("请先输入您要说的话后重试")
					_url = `${deviceApi.ORIGIN}/ouxuanac/tts/textToVoice.wav?text=${txt}&voice_type=4&speed=-1&volume=10`;
				}
				//已录音
				if(this.voicePadConfig.step==3){
					console.log("本地录音path:",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) {
						that.voicePadConfig.voiceUrl = _res.data.url
						console.log("上传成功后path:", 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,
							"text": this.voicePadConfig?.txt || ''
						}
					},	
					// "token": "f0d5c19b-b87e-11eb-bc7d-5254005df464"
				}
				//发送命令到中控
				if(_url)this.operateReq({
					data: DEVICE_FUN.AC_filterCloudACData(_data, that.curSwitch),
				})
				
			},
			//试听/播放 语音/录音 
			async listenVoice() {
				let self = this
				if(this.voicePadConfig.step==0){
					//需要将语音下载到本地,然后播放
					let txt = this.voicePadConfig.txt;
					if(!txt)return util.showNone("请先输入您要说的话后重试")
					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;
				}
				console.log('播放录音文件:', innerAudioContext.src);
				if(innerAudioContext.src)innerAudioContext.play();
			},
			getDownloadUrl(url) {
				console.log('下载录音');
				util.showLoad()
				return new Promise((rs,rj)=>{
					uni.downloadFile({
					    url: url, //资源路径e
					    success: (res) => {
					        if (res.statusCode === 200) {
					            console.log('下载成功',res);
								util.hideLoad()
								rs(res.tempFilePath)
					        }
					    },
						fail: (e) => {
							console.log('文字转录音文件下载失败',e);
							util.hideLoad()
					        rj(e)
					    },
						complete: (e) => {
							util.hideLoad()
						},
					});
				})
			},
			
			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 || [];
						
						//直接拿中控在线状态   做下临时处理先用中控状态的数据填一下
						let deviceInfo = uni.getStorageSync("deviceInfo");
						_list = _list.map((e,i)=>{
							 e['defineStatusCode'] = deviceInfo.Online==1? 1 : 0;
							return e
						})
						this.deviceList = _list;
						console.log(res)
						
						this.updateVoiceSlider();
					})
					.catch(util.hideLoad)
			},
			// 按钮操作， status 0 -> 关（左）， 1 -> 开（右）
			operateBtn: util.debounce(function({
				switchInfo,
				status
			}) {
				this.curSwitch = switchInfo || {};
				if (switchInfo.hardware_type === "AudioPlayer") return this.HandleVoiceOperate({
					switchInfo,
					status
				}); //单独处理音响操作0704


			}, 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,
				succFun,
				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) {
							succFun(res.data);
							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,
				// })
				//TODO 等待后续音响设备调试后,再开放更新设备状态功能
				 // _data = DEVICE_FUN.AC_filterCloudACData(data,switchInfo);
				// 后台：就没这个功能...
				util.showLoad();
				setTimeout(()=>util.hideLoad(),1000)
			}, 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',
					'YZK':'zzio404d-gpio-status'
				};

				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',
					'YZK':'zzio404d-gpio'
				};

				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',
					"XiaoHuiXiong":"xhx-lora-air-tcp"
				};
				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';
	page{
        background:url(../../static/images/page_bg.jpg) repeat-y;
        background-size: 100%;
        background-attachment: fixed;
    }
	.slider-box{
		margin-bottom: 40rpx;
		> text {
			margin-left: 30rpx;
			font-size: 24rpx;
			color: #fff;
		}
		> view{
			width: 100%;
			color: #fff;
			font-size: 28rpx;
			@include centerFlex(space-between);
			padding: 0 34rpx;
		}
	}
	.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: #1A1A1A;
		}

		text:last-child {
			width: 466rpx;
			color: #fff;
			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;
			border: .5px solid #fff;
			box-shadow: 0 4upx 12upx 0 #00987454, inset 0 0 40upx 0 #ffffff80;
            background-image: linear-gradient(180deg, #eff6f44d 0%, #FFFFFF 100%);
			.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: #1A1A1A;
						@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: .5px solid #fff;

				>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-around;
				align-items: center;
			}

		}
	}
</style>
