flex音频播放



<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:mx="library://ns.adobe.com/flex/mx"
      minWidth="955" minHeight="600"
      creationComplete="initMusic()"
      height="304" width="808">
 <s:layout>
  <s:BasicLayout/>
 </s:layout>
 <fx:Declarations>
  <!-- 将非可视元素(例如服务、值对象)放在此处 -->
 </fx:Declarations>
 
 <fx:Script>
  <![CDATA[
   import com.adobe.serialization.json.JSON;
   
   import flash.utils.ByteArray;
   
   import mx.collections.ArrayCollection;
   import mx.controls.Alert;
   import mx.core.UIComponent;
   import mx.events.IndexChangedEvent;
   import mx.managers.PopUpManager;
   import mx.printing.FlexPrintJob;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   import mx.rpc.http.HTTPService;

   
   private var serverIP:String = "http://127.0.0.1";
   private var ba:ByteArray = new ByteArray();
   private var soundRequest:URLRequest;
   private var sound:Sound = new Sound(); //使用Sound对象来获取音乐文件播放声音
   private var chanel:SoundChannel;       //引入SoundChannel对象来精确控制声音
   private var vol:SoundTransform;        //通过设置SoundTransform对象的volume属性控制音量
   
   private var stopPosition:int=0;        //使用stopPosition记录暂停音乐时的位置
   private var soundState:int=1;          //使用soundState记录是否静音
   private var soundValue:int=2;          //记录静音前的音量
   private var playState:int=0;           //使用playState记录声音是否被停止(包括暂停)
   private var totalTime:String = "00:00";//语音文件总时间
   private var params:Object;             //URL参数列表
   private var _sperite:Sprite;           //用于绘制声音波形
   
   //初始化
   private function initMusic():void{
    var args:Object = getParams();      //获取URL中的参数列表
    var file:String = serverIP + args.audio+".mp3";//得到语音文件名
//    file = "http://127.0.0.1/voice/3416.mp3";
    
    //对播放控制按钮和滑动条添加鼠标动作监听
    soundBtn.addEventListener(MouseEvent.CLICK,onSoundClick);//有声音
    soundBtnJ.addEventListener(MouseEvent.CLICK,onSoundClick);//静音
    playBtn.addEventListener(MouseEvent.CLICK,onPlayBtnClick);//播放
    pauseBtn.addEventListener(MouseEvent.CLICK,onPlayBtnClick);//暂停
    proccessBar.addEventListener(MouseEvent.MOUSE_DOWN,onProccessBarDown);//播放进度条
    proccessBar.addEventListener(MouseEvent.MOUSE_UP,onProccessBarUp);//播放进度条
    
    //组件初始状态设置
    soundSlide.value=2;//默认音量等于2
    
    if(file != null && file != ""){
     var buffer:SoundLoaderContext = new SoundLoaderContext(5000);
     soundRequest = new URLRequest(file);
     sound.load(soundRequest,buffer);
     sound.addEventListener(Event.COMPLETE, loaded);//监听加载事件
     sound.addEventListener(ProgressEvent.PROGRESS, progressHandler);//缓冲事件
    }
    
    //控制音量
    vol = new SoundTransform();
    vol.volume = soundSlide.value;
    
   }
   
   //缓冲事件方法
   private function progressHandler(event:ProgressEvent):void{
    //计算缓冲方框的宽度(滑块本身也有一定的宽度,减去约10个像素宽度)
    if (sound.bytesLoaded>0){
     bufferRect.width = sound.bytesLoaded / sound.bytesTotal*(proccessBar.width);
    } 
   }
   
   private function onProccessBarDown(e:MouseEvent):void{
    this.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
   }
   
   private function onProccessBarUp(e:MouseEvent):void{
    this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
   }
   
   //读取语音数据,一边取一边画
   private function loaded(event:Event):void {
    var width:Number = box.width;
    var height:Number =box.height;
    
    //获取语音长度,毫秒
    var lengthTime:Number = sound.length;
    totalTime = formatTime(lengthTime);
    playTime.text = totalTime;
    
    _sperite = new Sprite();//建立影片精灵  
    var uicomponent:UIComponent = new UIComponent(); 
    uicomponent.addChild(_sperite); 
    box.addElement(uicomponent);
    
    doDraw(0.1,0xffffff,0,height/2,width-2,height/2);  //绘制中心轴线
    //绘制横轴
    for(var i:int=20;i<height;i+=20){
     doDraw(0.1,0xCCCCCC,0,i,width-2,i);  //绘制中心轴线
    }
    //绘制纵轴
    for(var j:int=40;j<width;j+=40){
     doDraw(0.1,0xCCCCCC,j,0,j,height);  //绘制中心轴线
    }
    
    var dataCount:Number = lengthTime*44.1;
    sound.extract(ba, dataCount);  //将所有的语音数据读取到字节数组里面
    ba.position = 0;//文件指针的当前位置
    var startX:Number = 0,startY:Number = 100;//开始点
    var m:int = 1;//记录数据个数
    while(ba.bytesAvailable > 0){
     var value:Number = ba.readFloat();
     var endX:Number = m*width/dataCount;
     var endY:Number = height/2;
     endY = (1-value)*(height/2);//正数
     doDraw(0.1, 0x00FF00, startX, startY, endX, endY);//绘制波形
     startX = endX; startY = endY;
     if(ba.bytesAvailable > 0){
      ba.position += 84;
      m += 11;
     }
    }
    
    //完成自动播放
    playState=1;
    chanel = sound.play(stopPosition);
    chanel.soundTransform=vol;   
    this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
    playBtn.visible=false;
    pauseBtn.visible=true;
    pState.text = "状态: 播放";
    
    load.visible = false;
   }
   
   //绘制曲线
   private function doDraw(cx:Number,color:uint,startX:Number,startY:Number,endX:Number,endY:Number):void{ 
    _sperite.graphics.lineStyle(cx,color,1); 
    _sperite.graphics.moveTo(startX,startY); 
    _sperite.graphics.lineTo(endX,endY); 
   } 
   
   //播放暂停
   private function onPlayBtnClick(e:MouseEvent):void{
    //正常状态控制播放与暂停
    if(playState==1){
     playState=0; 
     stopPosition = chanel.position;
     chanel.stop();
     this.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
     playBtn.visible=true;
     pauseBtn.visible=false;
     pState.text = "状态: 暂停";
    }else if(playState==0){
     playState=1;
     chanel = sound.play(stopPosition);
     chanel.soundTransform=vol;   
     this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
     playBtn.visible=false;
     pauseBtn.visible=true;
     pState.text = "状态: 播放";
    }
   }
   
   //停止播放
   public function musStop():void{
    playState=0;
    stopPosition = 0;
    this.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
    proccessBar.value=0;
    playTime.text="00:00/"+totalTime;
    playBtn.visible=true;
    pauseBtn.visible=false;
    pState.text = "状态: 停止";
    if(chanel!=null){
     chanel.stop();
    }
   }
   
   //静音处理按钮
   private function onSoundClick(e:MouseEvent):void{
    //点击正常状态的静音按钮处理函数
    if(soundState==1){
     soundState=0;
     vol.volume=0;
     soundValue = soundSlide.value;
     soundSlide.value=0;
     soundBtnJ.visible=true;
     soundBtn.visible=false;
    }else if(soundState==0){
     soundState=1;
     soundSlide.value = soundValue;
     vol.volume=soundSlide.value;
     soundBtnJ.visible=false;
     soundBtn.visible=true;
    }
    chanel.soundTransform=vol;
   }
   
   //控制音量大小
   private function soundSlideChange():void{
    vol.volume=soundSlide.value;
    chanel.soundTransform=vol;
   }
   
   //控制播放进度
   private function onEnterFrame(e:Event):void{
    if(chanel!=null){
     proccessBar.value=chanel.position*(100/sound.length);
     playTime.text=formatTime(chanel.position) + "/" + totalTime;
     if(proccessBar.value>99){
      musStop();
     }
    }
   }
   
   //鼠标拖动进度条更改播放进度的处理
   private function changePos():void{
    if(chanel!=null){
     chanel.stop();
     //完成自动播放
     playState=1;
     chanel = sound.play(proccessBar.value*sound.length/100);
     chanel.soundTransform=vol;   
     this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
     playBtn.visible=false;
     pauseBtn.visible=true;
     pState.text = "状态: 播放";
    }
   }
   
   //时间格式处理
   private function formatTime(time:Number):String{
    var s:String;
    var m:Number = Math.floor(time / 60000);//分钟
    if(m >= 60){
     //小时
     var h:Number = Math.floor(m / 60);
     if (h < 10)
      s = "0" + h;
     else
      s = String(h);
     
     //分钟
     m = m - h*60;
     if (m < 10)
      s += ":0" + m;
     else
      s += ":" + String(m);
    }else{
     if (m < 10)
      s = "0" + m;
     else
      s = String(m);
    }
    
    m = Math.floor((time / 1000 ) % 60)
    if (m < 10)
     s += ":0" + m;
    else
     s += ":" + m;
    
    return s;
   }
   
   //从Url中得到参数,得到   ? 以后的所有
   private function getParams():Object {
    params = {};
    //获取整个URI
    var query:String = ExternalInterface.call("window.location.search.substring", 1);
    var url:String = ExternalInterface.call("window.location.href.toString", 1);
    var index:int = url.indexOf("dsas")
    serverIP = url.substring(0,index-1);
    
    if(query) {
     var pairs:Array = query.split("&");
     for(var i:uint=0; i < pairs.length; i++) {
      var pos:int = pairs[i].indexOf("=");
      if(pos != -1) {
       var argname:String = pairs[i].substring(0, pos);
       var value:String = pairs[i].substring(pos+1);
       params[argname] = value;
      }
     }
    }
    return params;
   }
   
   //下载语音文件
   private function downLoadsVoice():void{
    var args:Object = getParams();      //获取URL中的参数列表
    var fileName:String = args.audio;
    var file:String = serverIP + fileName + ".mp3";//得到语音文件名
    var urlReq:URLRequest = new URLRequest(file); 
    var fileRef:FileReference = new FileReference();
    var index:int = fileName.indexOf("voice/");
    var tempFile:String = fileName.substring(index+6,fileName.length)+".mp3";
    fileRef.download(urlReq,tempFile);
   }
  ]]>
 </fx:Script>
 
 <s:Panel id="panel" x="1.3" y="1.35" width="806" height="302" title="乘务员标准化作业语音监控系统"
    backgroundColor="#448FF5" backgroundAlpha="0.72" >
  
  <s:Label x="738" y="-24" text="状态:暂停" id="pState" color="#FF0404" fontWeight="bold"/>
  
  <s:BorderContainer x="2" y="2" width="800" height="200" id="box" backgroundColor="#0211D6">
   <s:Label x="260" y="84" text="语音加载完成后自动播放,请稍后..." id="load" fontSize="20" color="#FC0000" fontWeight="bold" fontStyle="italic" fontFamily="Courier New"/>
  </s:BorderContainer>
  
  <s:BorderContainer id="bufferRect" x="1" y="210" width="7" height="7" buttonMode="true" borderColor="red" backgroundColor="red">
  </s:BorderContainer>
  
  <s:HSlider x="1" y="207" width="801" id="proccessBar" change="changePos()"
       minimum="0" maximum="100" snapInterval="0.1" liveDragging="true"
       showDataTip="false" height="13" alpha="0.5" buttonMode="true"/>
  
  <mx:Image x="6" y="227" source="assets/play.png" id="playBtn"/>
  <mx:Image x="6" y="227" source="assets/pause.png" id="pauseBtn" visible="false"/>
  <mx:Image x="56" y="227" source="assets/stop.png" id="stopBtn" click="musStop()"/>
  <mx:Image x="106" y="227" source="assets/volume.png" id="soundBtn"/>
  <mx:Image x="106" y="227" source="assets/volumeJ.png" id="soundBtnJ" visible="false"/>
  <s:HSlider x="149" y="238" width="107" id="soundSlide" change="soundSlideChange()" minimum="0" maximum="5"/>
  <s:Label y="224" right="1" text="00:00" id="playTime"/>
  <s:Button x="758" y="247" label="下载" width="46" click="downLoadsVoice()" id="dl"/>
 </s:Panel>
</s:Application><?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600"
creationComplete="initMusic()"
height="304" width="808">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>

<fx:Script>
<![CDATA[
import com.adobe.serialization.json.JSON;

import flash.utils.ByteArray;

import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.events.IndexChangedEvent;
import mx.managers.PopUpManager;
import mx.printing.FlexPrintJob;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;


private var serverIP:String = "http://127.0.0.1";
private var ba:ByteArray = new ByteArray();
private var soundRequest:URLRequest;
private var sound:Sound = new Sound(); //使用Sound对象来获取音乐文件播放声音
private var chanel:SoundChannel; //引入SoundChannel对象来精确控制声音
private var vol:SoundTransform; //通过设置SoundTransform对象的volume属性控制音量

private var stopPosition:int=0; //使用stopPosition记录暂停音乐时的位置
private var soundState:int=1; //使用soundState记录是否静音
private var soundValue:int=2; //记录静音前的音量
private var playState:int=0; //使用playState记录声音是否被停止(包括暂停)
private var totalTime:String = "00:00";//语音文件总时间
private var params:Object; //URL参数列表
private var _sperite:Sprite; //用于绘制声音波形

//初始化
private function initMusic():void{
var args:Object = getParams(); //获取URL中的参数列表
var file:String = serverIP + args.audio+".mp3";//得到语音文件名
// file = "http://127.0.0.1/voice/3416.mp3";

//对播放控制按钮和滑动条添加鼠标动作监听
soundBtn.addEventListener(MouseEvent.CLICK,onSoundClick);//有声音
soundBtnJ.addEventListener(MouseEvent.CLICK,onSoundClick);//静音
playBtn.addEventListener(MouseEvent.CLICK,onPlayBtnClick);//播放
pauseBtn.addEventListener(MouseEvent.CLICK,onPlayBtnClick);//暂停
proccessBar.addEventListener(MouseEvent.MOUSE_DOWN,onProccessBarDown);//播放进度条
proccessBar.addEventListener(MouseEvent.MOUSE_UP,onProccessBarUp);//播放进度条

//组件初始状态设置
soundSlide.value=2;//默认音量等于2

if(file != null && file != ""){
var buffer:SoundLoaderContext = new SoundLoaderContext(5000);
soundRequest = new URLRequest(file);
sound.load(soundRequest,buffer);
sound.addEventListener(Event.COMPLETE, loaded);//监听加载事件
sound.addEventListener(ProgressEvent.PROGRESS, progressHandler);//缓冲事件
}

//控制音量
vol = new SoundTransform();
vol.volume = soundSlide.value;

}

//缓冲事件方法
private function progressHandler(event:ProgressEvent):void{
//计算缓冲方框的宽度(滑块本身也有一定的宽度,减去约10个像素宽度)
if (sound.bytesLoaded>0){
bufferRect.width = sound.bytesLoaded / sound.bytesTotal*(proccessBar.width);
}
}

private function onProccessBarDown(e:MouseEvent):void{
this.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
}

private function onProccessBarUp(e:MouseEvent):void{
this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
}

//读取语音数据,一边取一边画
private function loaded(event:Event):void {
var width:Number = box.width;
var height:Number =box.height;

//获取语音长度,毫秒
var lengthTime:Number = sound.length;
totalTime = formatTime(lengthTime);
playTime.text = totalTime;

_sperite = new Sprite();//建立影片精灵
var uicomponent:UIComponent = new UIComponent();
uicomponent.addChild(_sperite);
box.addElement(uicomponent);

doDraw(0.1,0xffffff,0,height/2,width-2,height/2); //绘制中心轴线
//绘制横轴
for(var i:int=20;i<height;i+=20){
doDraw(0.1,0xCCCCCC,0,i,width-2,i); //绘制中心轴线
}
//绘制纵轴
for(var j:int=40;j<width;j+=40){
doDraw(0.1,0xCCCCCC,j,0,j,height); //绘制中心轴线
}

var dataCount:Number = lengthTime*44.1;
sound.extract(ba, dataCount); //将所有的语音数据读取到字节数组里面
ba.position = 0;//文件指针的当前位置
var startX:Number = 0,startY:Number = 100;//开始点
var m:int = 1;//记录数据个数
while(ba.bytesAvailable > 0){
var value:Number = ba.readFloat();
var endX:Number = m*width/dataCount;
var endY:Number = height/2;
endY = (1-value)*(height/2);//正数
doDraw(0.1, 0x00FF00, startX, startY, endX, endY);//绘制波形
startX = endX; startY = endY;
if(ba.bytesAvailable > 0){
ba.position += 84;
m += 11;
}
}

//完成自动播放
playState=1;
chanel = sound.play(stopPosition);
chanel.soundTransform=vol;
this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
playBtn.visible=false;
pauseBtn.visible=true;
pState.text = "状态: 播放";

load.visible = false;
}

//绘制曲线
private function doDraw(cx:Number,color:uint,startX:Number,startY:Number,endX:Number,endY:Number):void{
_sperite.graphics.lineStyle(cx,color,1);
_sperite.graphics.moveTo(startX,startY);
_sperite.graphics.lineTo(endX,endY);
}

//播放暂停
private function onPlayBtnClick(e:MouseEvent):void{
//正常状态控制播放与暂停
if(playState==1){
playState=0;
stopPosition = chanel.position;
chanel.stop();
this.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
playBtn.visible=true;
pauseBtn.visible=false;
pState.text = "状态: 暂停";
}else if(playState==0){
playState=1;
chanel = sound.play(stopPosition);
chanel.soundTransform=vol;
this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
playBtn.visible=false;
pauseBtn.visible=true;
pState.text = "状态: 播放";
}
}

//停止播放
public function musStop():void{
playState=0;
stopPosition = 0;
this.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
proccessBar.value=0;
playTime.text="00:00/"+totalTime;
playBtn.visible=true;
pauseBtn.visible=false;
pState.text = "状态: 停止";
if(chanel!=null){
chanel.stop();
}
}

//静音处理按钮
private function onSoundClick(e:MouseEvent):void{
//点击正常状态的静音按钮处理函数
if(soundState==1){
soundState=0;
vol.volume=0;
soundValue = soundSlide.value;
soundSlide.value=0;
soundBtnJ.visible=true;
soundBtn.visible=false;
}else if(soundState==0){
soundState=1;
soundSlide.value = soundValue;
vol.volume=soundSlide.value;
soundBtnJ.visible=false;
soundBtn.visible=true;
}
chanel.soundTransform=vol;
}

//控制音量大小
private function soundSlideChange():void{
vol.volume=soundSlide.value;
chanel.soundTransform=vol;
}

//控制播放进度
private function onEnterFrame(e:Event):void{
if(chanel!=null){
proccessBar.value=chanel.position*(100/sound.length);
playTime.text=formatTime(chanel.position) + "/" + totalTime;
if(proccessBar.value>99){
musStop();
}
}
}

//鼠标拖动进度条更改播放进度的处理
private function changePos():void{
if(chanel!=null){
chanel.stop();
//完成自动播放
playState=1;
chanel = sound.play(proccessBar.value*sound.length/100);
chanel.soundTransform=vol;
this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
playBtn.visible=false;
pauseBtn.visible=true;
pState.text = "状态: 播放";
}
}

//时间格式处理
private function formatTime(time:Number):String{
var s:String;
var m:Number = Math.floor(time / 60000);//分钟
if(m >= 60){
//小时
var h:Number = Math.floor(m / 60);
if (h < 10)
s = "0" + h;
else
s = String(h);

//分钟
m = m - h*60;
if (m < 10)
s += ":0" + m;
else
s += ":" + String(m);
}else{
if (m < 10)
s = "0" + m;
else
s = String(m);
}

m = Math.floor((time / 1000 ) % 60)
if (m < 10)
s += ":0" + m;
else
s += ":" + m;

return s;
}

//从Url中得到参数,得到 ? 以后的所有
private function getParams():Object {
params = {};
//获取整个URI
var query:String = ExternalInterface.call("window.location.search.substring", 1);
var url:String = ExternalInterface.call("window.location.href.toString", 1);
var index:int = url.indexOf("dsas")
serverIP = url.substring(0,index-1);

if(query) {
var pairs:Array = query.split("&");
for(var i:uint=0; i < pairs.length; i++) {
var pos:int = pairs[i].indexOf("=");
if(pos != -1) {
var argname:String = pairs[i].substring(0, pos);
var value:String = pairs[i].substring(pos+1);
params[argname] = value;
}
}
}
return params;
}

//下载语音文件
private function downLoadsVoice():void{
var args:Object = getParams(); //获取URL中的参数列表
var fileName:String = args.audio;
var file:String = serverIP + fileName + ".mp3";//得到语音文件名
var urlReq:URLRequest = new URLRequest(file);
var fileRef:FileReference = new FileReference();
var index:int = fileName.indexOf("voice/");
var tempFile:String = fileName.substring(index+6,fileName.length)+".mp3";
fileRef.download(urlReq,tempFile);
}
]]>
</fx:Script>

<s:Panel id="panel" x="1.3" y="1.35" width="806" height="302" title="乘务员标准化作业语音监控系统"
backgroundColor="#448FF5" backgroundAlpha="0.72" >

<s:Label x="738" y="-24" text="状态:暂停" id="pState" color="#FF0404" fontWeight="bold"/>

<s:BorderContainer x="2" y="2" width="800" height="200" id="box" backgroundColor="#0211D6">
<s:Label x="260" y="84" text="语音加载完成后自动播放,请稍后..." id="load" fontSize="20" color="#FC0000" fontWeight="bold" fontStyle="italic" fontFamily="Courier New"/>
</s:BorderContainer>

<s:BorderContainer id="bufferRect" x="1" y="210" width="7" height="7" buttonMode="true" borderColor="red" backgroundColor="red">
</s:BorderContainer>

<s:HSlider x="1" y="207" width="801" id="proccessBar" change="changePos()"
minimum="0" maximum="100" snapInterval="0.1" liveDragging="true"
showDataTip="false" height="13" alpha="0.5" buttonMode="true"/>

<mx:Image x="6" y="227" source="assets/play.png" id="playBtn"/>
<mx:Image x="6" y="227" source="assets/pause.png" id="pauseBtn" visible="false"/>
<mx:Image x="56" y="227" source="assets/stop.png" id="stopBtn" click="musStop()"/>
<mx:Image x="106" y="227" source="assets/volume.png" id="soundBtn"/>
<mx:Image x="106" y="227" source="assets/volumeJ.png" id="soundBtnJ" visible="false"/>
<s:HSlider x="149" y="238" width="107" id="soundSlide" change="soundSlideChange()" minimum="0" maximum="5"/>
<s:Label y="224" right="1" text="00:00" id="playTime"/>
<s:Button x="758" y="247" label="下载" width="46" click="downLoadsVoice()" id="dl"/>
</s:Panel>
</s:Application>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值