addVoice.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. <template>
  2. <view class="add-voice-page">
  3. <van-field
  4. :value="form.title"
  5. placeholder="请输入语音标题"
  6. :border="false"
  7. clearable
  8. @change="inputChange"
  9. label="语音标题"
  10. />
  11. <van-field
  12. :value="form.variety_name"
  13. placeholder="请选择品种"
  14. :border="false"
  15. readonly
  16. is-link
  17. label="品种"
  18. @click-input="showFilter=true"
  19. @click-icon="showFilter=true"
  20. />
  21. <van-field
  22. :value="form.section_name"
  23. placeholder="请选择板块名称"
  24. :border="false"
  25. readonly
  26. is-link
  27. label="板块名称"
  28. @click-input="showFilter=true"
  29. @click-icon="showFilter=true"
  30. />
  31. <!-- 上传图片部分 -->
  32. <view
  33. class="flex upload-img-box"
  34. v-if="recorderStatus!=='doing'&&recorderStatus!=='pause'"
  35. :style="[{'height':recorderStatus==='stop'&&'auto'},{'border-bottom':recorderStatus==='stop'?'1px solid #E6E6E6':''}]"
  36. >
  37. <view class="item" v-for="(item,index) in imgList" :key="item" @click="handlePreViewImg(item)">
  38. <image :src="item" mode="aspectFill"/>
  39. <view class="del-btn" @click.stop="handleDelImg(index)">
  40. <van-icon name="cross" size="12" style="position: absolute;left:16rpx;top:8rpx" color="#ffffff"/>
  41. </view>
  42. </view>
  43. <view class="item add-btn" @click="handleUploadImg" v-if="imgList.length<5">
  44. <image src="./static/camera.png" mode="aspectFill" />
  45. </view>
  46. </view>
  47. <view class="flex audio-box" v-if="recorderStatus==='stop'">
  48. <image
  49. :src="temAudio.paused?'../../../static/voice/pause.png':'../../../static/voice/playing.png'"
  50. mode="aspectFill"
  51. @click="handlePlayAudio"
  52. />
  53. <slider
  54. activeColor="#E6B77D"
  55. :max="temAudio.duration"
  56. :value="temAudio.curTime"
  57. @change="handleAudioSliderChange($event)"
  58. block-size="12"
  59. class="slider"
  60. />
  61. <text class="left-time">{{temAudio.curTime|formatTime}}</text>
  62. <text class="right-time">{{temAudio.duration|formatTime}}</text>
  63. <view class="del-btn" @click="handleDelRecord">
  64. <image src="./static/del.png" mode="aspectFill" />
  65. <text>删除</text>
  66. </view>
  67. <view class="pre_publish_time" v-if="voiceId!=0">定时发布时间:{{pre_publish_time}}</view>
  68. </view>
  69. <!-- <view class="empty-voice-box" v-if="recorderStatus==='start'">
  70. <image src="./static/record.png" mode="aspectFill" />
  71. <view>无录音(录音时长超过十分钟自动结束)</view>
  72. </view> -->
  73. <view class="animat-box" v-if="recorderStatus==='doing'||recorderStatus==='pause'">
  74. <view class="con-box">
  75. <image :class="['img move1',recorderStatus==='doing'?'animat-run':'animat-pause']" src="./static/record-img.png" mode="widthFix" />
  76. <image :class="['img move2',recorderStatus==='doing'?'animat-run':'animat-pause']" src="./static/record-img.png" mode="widthFix" />
  77. <image :class="['img move3',recorderStatus==='doing'?'animat-run':'animat-pause']" src="./static/record-img.png" mode="widthFix" />
  78. </view>
  79. <view class="bot-text">{{time|formatTime}}</view>
  80. </view>
  81. <view class="sound-record-wrap" v-if="recorderStatus!=='stop'">
  82. <view class="top-text" v-show="recorderStatus=='start'">点击开始录音</view>
  83. <image class="btn" :src="btnImg" mode="aspectFill" @click="handleClickBtn" />
  84. <view
  85. class="del-btn"
  86. :style="{color:recorderStatus==='doing'&&'#999'}"
  87. v-if="recorderStatus!=='start'"
  88. @click="handleResetRecorder"
  89. >删除</view>
  90. <view
  91. class="done-btn"
  92. v-if="recorderStatus!=='start'"
  93. @click="handleEndRecorder"
  94. >完成</view>
  95. <view style="text-align:center;color:#999;margin-top:44rpx" v-if="recorderStatus==='start'">无录音(录音时长超过十分钟自动结束)</view>
  96. </view>
  97. <view class="publish-btn" v-if="recorderStatus==='stop'">
  98. <text @click="handlePublish('time')">定时发布</text>
  99. <text @click="handlePublish">立即发布</text>
  100. </view>
  101. <!-- 筛选弹窗 -->
  102. <van-popup
  103. :show="showFilter"
  104. position="bottom"
  105. :close-on-click-overlay="true"
  106. @close="showFilter = false"
  107. round
  108. >
  109. <view class="fliter-wrap-list">
  110. <view class="flex top">
  111. <text style="color:#000">全部选项</text>
  112. <text style="color:#E3B377" @click="showFilter=false">取消</text>
  113. </view>
  114. <van-tree-select
  115. :items="options"
  116. :main-active-index="mainActiveIndex"
  117. :active-id="activeId"
  118. @click-nav="onClickNav"
  119. @click-item="onClickItem"
  120. main-active-class="main-active-class"
  121. content-active-class="content-active-class"
  122. />
  123. </view>
  124. </van-popup>
  125. <!-- 选择时间弹窗 -->
  126. <van-popup
  127. :show="showTime"
  128. position="bottom"
  129. :close-on-click-overlay="true"
  130. @close="showTime = false"
  131. round
  132. >
  133. <van-datetime-picker
  134. title="设置发布时间"
  135. type="datetime"
  136. :value="selectTime"
  137. :min-date="minDate"
  138. @confirm="handleConfirmTime"
  139. @cancel="showTime = false"
  140. />
  141. </van-popup>
  142. <!-- <van-dialog id="van-dialog" /> -->
  143. <!-- 发布弹窗 -->
  144. <van-dialog
  145. use-slot
  146. :show="showPublish"
  147. confirm-button-text="发布且推送"
  148. cancel-button-text="仅发布"
  149. show-cancel-button
  150. @confirm="handleConfirmPublish(1)"
  151. @cancel="handleConfirmPublish(0)"
  152. @close="showPublish=false"
  153. >
  154. <view style="padding:40px 20px 20px;text-align:center;position: relative;">
  155. 发布后将推送模板消息和客群,确认发布吗?
  156. <van-icon name="cross" size="20" style="position: absolute;right:10px;top:10px" color="#6666" @click="showPublish=false"/>
  157. </view>
  158. </van-dialog>
  159. <!-- 定时发布提示弹窗 -->
  160. <van-dialog
  161. use-slot
  162. :show="showTimeAttention"
  163. confirm-button-text="知道了"
  164. confirm-button-color="#E3B377"
  165. @confirm="showTime=true"
  166. @close="showTimeAttention=false,showTime=true"
  167. >
  168. <view style="padding:40px 20px 20px;text-align:center;position: relative;">
  169. 设置定时发布后,会在设定的时间发布语音播报并推送模板消息
  170. <van-icon name="cross" size="20" style="position: absolute;right:10px;top:10px" color="#666" @click="showTimeAttention=false,showTime=true"/>
  171. </view>
  172. </van-dialog>
  173. </view>
  174. </template>
  175. <script>
  176. import {apiVoiceSectionList,apiVoiceSendMsg,apiVoiceAdd,apiVoiceEdit,apiVoicePublish,apiVoiceDetail} from '@/api/voice'
  177. import {baseApiUrl} from '@/utils/config.js'
  178. import {apiGetSceneToParams} from '@/api/common'
  179. import CryptoJS from '@/utils/crypto.js'
  180. import uniAsync from "@/utils/uni-async.js"; // uni api async 化
  181. import {uploadImg,commonUploadAudio} from '@/utils/upload'
  182. const dayjs=require('@/utils/dayjs.min')
  183. const recorderManager = wx.getRecorderManager();//录音实例
  184. let innerAudioContext = uni.createInnerAudioContext();//播放音频实例
  185. let TIMER=null//计时器
  186. export default {
  187. filters:{
  188. formatTime(e){
  189. let m=parseInt(e/60)
  190. let s=parseInt(e%60)
  191. return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
  192. }
  193. },
  194. computed:{
  195. btnImg(){
  196. if(this.recorderStatus==='start'){
  197. return './static/voice-start.png'
  198. }else if(this.recorderStatus==='doing'){
  199. return './static/voice-doing.png'
  200. }else if(this.recorderStatus==='stop'){
  201. return './static/voice-pause.png'
  202. }else if(this.recorderStatus==='pause'){
  203. return './static/voice-pause.png'
  204. }
  205. }
  206. },
  207. data() {
  208. return {
  209. form:{
  210. title:'',//语音标题
  211. variety_name:'',
  212. variety_id:'',
  213. section_id:'',
  214. section_name:'',
  215. img_url:'',//分享时的底图
  216. },
  217. voiceId:0,
  218. voiceUrl:'',//编辑音频地址
  219. pre_publish_time:'',
  220. recorderStatus:'start',//当前录音状态 start开始 doing正在录音 stop停止录音 pause录音暂停
  221. time:0,
  222. isReset:false,//是否点击了重置
  223. temAudio:{
  224. url:'',//音频地址
  225. duration:'',//时长
  226. size:'',//大小
  227. curTime:0,//播放时当前播放的时间
  228. paused:true,
  229. },//临时音频文件信息
  230. showFilter:false,
  231. options:[],
  232. mainActiveIndex:0,
  233. activeId:0,//选择的板块id
  234. showPublish:false,
  235. imgList:[],
  236. showTime:false,
  237. showTimeAttention:false,
  238. selectTime:new Date().getTime(),
  239. minDate:new Date().getTime()+600000,
  240. }
  241. },
  242. onLoad(options){
  243. // 调取用户授权使用麦克风
  244. uni.authorize({
  245. scope: 'scope.record',
  246. success() {}
  247. })
  248. this.listenVoice()
  249. this.getOptionsList()
  250. this.init(options)
  251. },
  252. onShow(){
  253. innerAudioContext = uni.createInnerAudioContext()
  254. this.listenAudio()
  255. },
  256. onHide(){
  257. innerAudioContext.destroy()
  258. this.temAudio.paused=true
  259. },
  260. onUnload(){
  261. innerAudioContext.destroy()
  262. clearInterval(TIMER)
  263. },
  264. methods: {
  265. async init(options){
  266. if(options.scene){
  267. const res=await apiGetSceneToParams({scene_key:options.scene})
  268. if(res.code===200){
  269. const obj=JSON.parse(res.data)
  270. this.voiceId=Number(obj.voiceId)
  271. this.getVoiceDetail()
  272. }
  273. }else if(options.voiceId){
  274. this.voiceId=Number(options.voiceId)
  275. this.getVoiceDetail()
  276. }
  277. },
  278. //语音详情
  279. async getVoiceDetail(){
  280. uni.setNavigationBarTitle({ title: '编辑语音' })
  281. const res=await apiVoiceDetail({broadcast_id:Number(this.voiceId)})
  282. if(res.code===200){
  283. this.form.title=res.data.BroadcastName
  284. this.form.variety_name=res.data.VarietyName
  285. this.form.variety_id=res.data.VarietyId
  286. this.form.section_id=res.data.SectionId
  287. this.form.section_name=res.data.SectionName
  288. this.voiceUrl=res.data.VoiceUrl
  289. this.temAudio.url=res.data.VoiceUrl
  290. this.temAudio.duration=res.data.VoicePlaySeconds
  291. this.temAudio.size=res.data.VoiceSize
  292. this.activeId=res.data.SectionId
  293. this.imgList=res.data.Imgs||[]
  294. this.pre_publish_time=dayjs(res.data.PrePublishTime).format('YYYY-MM-DD HH:mm')
  295. this.selectTime=dayjs(res.data.PrePublishTime).valueOf()
  296. this.recorderStatus='stop'
  297. }
  298. },
  299. //录音事件
  300. listenVoice(){
  301. recorderManager.onStart(()=>{
  302. //录音开始监听事件
  303. console.log('开始录音');
  304. this.recorderStatus='doing'
  305. this.isReset=false
  306. if(!TIMER){
  307. TIMER=setInterval(() => {
  308. this.time++
  309. }, 1000);
  310. }
  311. })
  312. recorderManager.onPause(()=>{
  313. //录音暂停监听事件
  314. console.log('录音暂停');
  315. this.recorderStatus='pause'
  316. clearInterval(TIMER)
  317. TIMER=null
  318. })
  319. recorderManager.onResume(()=>{
  320. //录音继续监听事件
  321. console.log('录音继续');
  322. this.recorderStatus='doing'
  323. if(!TIMER){
  324. TIMER=setInterval(() => {
  325. this.time++
  326. }, 1000);
  327. }
  328. })
  329. recorderManager.onStop((e)=>{
  330. //录音结束监听事件
  331. console.log('录音结束',e);
  332. // 如果是点击重置(删除按钮)的 则不做结束处理
  333. if(!this.isReset){
  334. this.recorderStatus='stop'
  335. this.temAudio.url=e.tempFilePath
  336. this.temAudio.size=e.fileSize
  337. this.temAudio.duration=parseInt(e.duration/1000)
  338. }
  339. clearInterval(TIMER)
  340. TIMER=null
  341. })
  342. recorderManager.onError((e)=>{
  343. //录音事件错误监听
  344. console.log('录音错误哦',e);
  345. })
  346. },
  347. //点击录音操作按钮
  348. async handleClickBtn(){
  349. const setRes=await uniAsync.getSetting()
  350. console.log(setRes.authSetting['scope.record']);
  351. if(!setRes.authSetting['scope.record']){
  352. uni.showToast({
  353. title:'请打开麦克风交流',
  354. icon:'none'
  355. })
  356. uni.openSetting()
  357. return
  358. }
  359. if(this.recorderStatus==='start'){
  360. recorderManager.start({
  361. duration:600000,
  362. format:'mp3'
  363. })
  364. }
  365. if(this.recorderStatus==='doing'){
  366. recorderManager.pause()//暂停录音
  367. }
  368. if(this.recorderStatus==='pause'){
  369. recorderManager.resume()//继续录音
  370. }
  371. },
  372. //点击重置录音状态
  373. handleResetRecorder(){
  374. if(this.recorderStatus==='doing') return
  375. this.isReset=true
  376. recorderManager.stop()
  377. this.recorderStatus='start'
  378. this.handleDelRecord()
  379. },
  380. //点击完成录音
  381. handleEndRecorder(){
  382. //点击完成时还不是已结束录音状态
  383. this.isReset=false
  384. recorderManager.stop()
  385. },
  386. //拖动音频播放进度条
  387. handleAudioSliderChange(e){
  388. const value=e.detail.value
  389. innerAudioContext.seek(value)
  390. },
  391. //点击播放\暂停音频
  392. handlePlayAudio(){
  393. innerAudioContext.src=this.temAudio.url
  394. innerAudioContext.obeyMuteSwitch=false
  395. if(this.temAudio.paused){
  396. innerAudioContext.play()
  397. }else{
  398. innerAudioContext.pause()
  399. }
  400. },
  401. //音频播放事件
  402. listenAudio(){
  403. innerAudioContext.onPlay(()=>{
  404. console.log('开始播放录音');
  405. this.temAudio.paused=false
  406. })
  407. innerAudioContext.onPause(()=>{
  408. console.log('录音播放暂停');
  409. this.temAudio.paused=true
  410. })
  411. // innerAudioContext.onStop(()=>{
  412. // console.log('录音播放停止');
  413. // this.temAudio.paused=true
  414. // innerAudioContext.src=''
  415. // })
  416. innerAudioContext.onEnded(()=>{
  417. console.log('录音播放自然结束');
  418. this.temAudio.curTime=this.temAudio.duration
  419. setTimeout(() => {
  420. this.temAudio.paused=true
  421. innerAudioContext.src=''
  422. this.temAudio.curTime=0
  423. }, 300);
  424. })
  425. innerAudioContext.onTimeUpdate(()=>{
  426. this.temAudio.curTime=parseInt(innerAudioContext.currentTime)
  427. })
  428. },
  429. //删除录音记录
  430. handleDelRecord(){
  431. this.recorderStatus='start'
  432. this.isReset=true
  433. this.temAudio.url=''
  434. this.temAudio.duration=''
  435. this.temAudio.curTime=0
  436. this.temAudio.paused=true
  437. this.time=0
  438. innerAudioContext.stop()
  439. TIMER=null
  440. },
  441. //获取选项数据
  442. async getOptionsList(){
  443. const res=await apiVoiceSectionList()
  444. if(!res.code===200) return
  445. const arr=res.data||[]
  446. this.options=arr.filter(item=>{
  447. item.text=item.VarietyName
  448. item.children=item.Children.filter(_item=>{
  449. if(_item.Status===1){
  450. _item.text=_item.SectionName
  451. _item.id=_item.SectionId
  452. return _item
  453. }
  454. })
  455. if(item.children.length>0){
  456. delete item.Children
  457. return item
  458. }
  459. })
  460. },
  461. onClickNav({detail}){
  462. console.log(detail);
  463. this.mainActiveIndex=detail.index
  464. },
  465. onClickItem({detail}){
  466. console.log(detail);
  467. this.activeId=detail.id
  468. this.form.section_id=detail.SectionId
  469. this.form.section_name=detail.SectionName
  470. this.form.variety_name=this.options[this.mainActiveIndex].VarietyName
  471. this.form.variety_id=this.options[this.mainActiveIndex].VarietyId
  472. this.form.img_url=detail.ImgUrl
  473. this.showFilter=false
  474. },
  475. inputChange(event) {
  476. this.form.title=event.detail
  477. },
  478. // 发布
  479. async handlePublish(type){
  480. if(!this.form.title||!this.form.variety_id){
  481. uni.showToast({
  482. title:'请将内容填写完整',
  483. icon:'none'
  484. })
  485. return
  486. }
  487. if(type==='time'){//定时发布
  488. this.showTimeAttention=true
  489. }else{
  490. this.showPublish=true
  491. }
  492. },
  493. //确认发布 publishType 发布类型: 0-仅发布 1-发布并推送 2-定时发布
  494. async handleConfirmPublish(publishType){
  495. //上传音频
  496. if(this.temAudio.url!=this.voiceUrl){
  497. const voiceRes=await commonUploadAudio(this.temAudio.url)
  498. if(voiceRes.code===200){
  499. this.temAudio.url=voiceRes.data.audio_url
  500. }
  501. }
  502. //新增、编辑语音
  503. let params={
  504. broadcast_name:this.form.title,
  505. section_id:Number(this.form.section_id),
  506. section_name:this.form.section_name,
  507. variety_id:Number(this.form.variety_id),
  508. variety_name:this.form.variety_name,
  509. author_id:Number(this.$store.state.user.userInfo.user_id),
  510. author:this.$store.state.user.userInfo.real_name,
  511. imgs:this.imgList.join(','),
  512. voice_seconds:this.temAudio.duration.toString(),
  513. voice_size:this.temAudio.size.toString(),
  514. voice_url:this.temAudio.url
  515. }
  516. wx.showLoading({
  517. title: '发布中...',
  518. mask: true,
  519. success: (result) => {},
  520. fail: () => {},
  521. complete: () => {}
  522. });
  523. let addRes=null
  524. if(this.voiceId!=0){//编辑语音
  525. params.broadcast_id=this.voiceId
  526. addRes=await apiVoiceEdit(params)
  527. }else{
  528. addRes=await apiVoiceAdd(params)
  529. }
  530. if(addRes.code===200){
  531. let par={
  532. broadcast_id:addRes.data.BroadcastId,
  533. }
  534. if(publishType===2){//定时发布
  535. par.publish_type=2
  536. par.pre_publish_time=dayjs(this.selectTime).format('YYYY-MM-DD HH:mm:ss')
  537. }else{
  538. par.publish_type=1
  539. }
  540. //发布语音
  541. const publishRes=await apiVoicePublish(par)
  542. wx.hideLoading();
  543. if(publishRes.code===200){
  544. if(publishType==0){//仅发布
  545. uni.showToast({
  546. title:'发布成功',
  547. icon:'success'
  548. })
  549. setTimeout(() => {
  550. uni.$emit('addVoiceSuccess')
  551. uni.navigateBack()
  552. }, 1000);
  553. }else if(publishType==1){//发布并推送
  554. this.handleSendMsg(addRes.data.BroadcastId)
  555. }else{////定时发布
  556. uni.showToast({
  557. title:'定时发布成功',
  558. icon:'success'
  559. })
  560. setTimeout(() => {
  561. uni.$emit('addVoiceSuccess')
  562. uni.navigateBack()
  563. }, 1000);
  564. }
  565. }else{
  566. uni.showToast({
  567. title:publishRes.msg,
  568. icon:'none'
  569. })
  570. }
  571. }else{
  572. wx.hideLoading();
  573. uni.showToast({
  574. title:addRes.msg,
  575. icon:'none'
  576. })
  577. }
  578. },
  579. //推送消息
  580. handleSendMsg(id){
  581. apiVoiceSendMsg({broadcast_id:id}).then(res=>{
  582. if(res.code===200){
  583. uni.showToast({
  584. title:"发布&推送成功",
  585. icon:'success'
  586. })
  587. setTimeout(() => {
  588. uni.$emit('addVoiceSuccess')
  589. uni.navigateBack()
  590. }, 1000);
  591. }
  592. })
  593. },
  594. //图片上传
  595. handleUploadImg(e){
  596. uploadImg({count:5-this.imgList.length}).then(res=>{
  597. this.imgList=[...this.imgList,...res]
  598. }).catch(err=>{
  599. console.log(err);
  600. if(err.errMsg=='chooseImage:fail cancel') return
  601. uni.showToast({
  602. title:'上传失败,请重试!',
  603. icon:'none'
  604. })
  605. })
  606. },
  607. //预览图片
  608. handlePreViewImg(item){
  609. wx.previewImage({
  610. urls:this.imgList,
  611. current:item
  612. })
  613. },
  614. //删除图片
  615. handleDelImg(index){
  616. this.imgList.splice(index,1)
  617. },
  618. //选择时间
  619. handleConfirmTime(e){
  620. this.selectTime=e.detail
  621. this.showTime=false
  622. this.handleConfirmPublish(2)
  623. },
  624. },
  625. }
  626. </script>
  627. <style lang="scss">
  628. .add-voice-page .van-cell{
  629. border-bottom: 1px solid #e5e5e5;
  630. }
  631. .add-voice-page .van-field__label{
  632. font-size: 32rpx;
  633. color: #333;
  634. }
  635. /* .add-voice-page .van-cell__title{
  636. max-width: 6.2em;
  637. min-width: 6.2em;
  638. margin-right: 12px;
  639. font-size: 32rpx;
  640. color: #333;
  641. } */
  642. .add-voice-page .van-cell__value{
  643. text-align: left;
  644. font-size: 32rpx;
  645. }
  646. .add-voice-page{
  647. .fliter-wrap-list{
  648. background-color: #fff;
  649. padding-top: 53rpx;
  650. .top{
  651. font-size: 32rpx;
  652. justify-content: space-between;
  653. margin-bottom: 40rpx;
  654. padding: 0 34rpx;
  655. }
  656. .van-sidebar{
  657. flex-shrink: 0;
  658. }
  659. .van-tree-select__content{
  660. overflow-x: hidden;
  661. }
  662. .main-active-class{
  663. border-color: #E3B377;
  664. }
  665. .content-active-class{
  666. color: #E3B377;
  667. }
  668. }
  669. }
  670. page{
  671. padding-bottom:constant(safe-area-inset-bottom);
  672. padding-bottom:env(safe-area-inset-bottom);
  673. }
  674. </style>
  675. <style lang="scss" scoped>
  676. .add-voice-page{
  677. .empty-voice-box{
  678. height: 36vh;
  679. padding-top: 150rpx;
  680. image{
  681. width: 140rpx;
  682. height: 140rpx;
  683. margin-bottom: 20rpx;
  684. }
  685. text-align: center;
  686. color: #999999;
  687. }
  688. .sound-record-wrap{
  689. border-top: 1px solid #E6E6E6;
  690. padding-top: 126rpx;
  691. position: relative;
  692. .top-text{
  693. text-align: center;
  694. color: #EE3636;
  695. position: absolute;
  696. top: 50rpx;
  697. left: 50%;
  698. transform: translateX(-50%);
  699. }
  700. .btn{
  701. width: 118rpx;
  702. height: 118rpx;
  703. display: block;
  704. margin-left: auto;
  705. margin-right: auto;
  706. }
  707. .del-btn{
  708. position: absolute;
  709. left: 122rpx;
  710. bottom: 40rpx;
  711. font-size: 32rpx;
  712. color: #EE3636;
  713. }
  714. .done-btn{
  715. position: absolute;
  716. right: 122rpx;
  717. bottom: 40rpx;
  718. font-size: 32rpx;
  719. color: #EE3636;
  720. }
  721. }
  722. .audio-box{
  723. background-color: #FDF8F2;
  724. height: 123rpx;
  725. align-items: center;
  726. margin-left: 34rpx;
  727. margin-right: 34rpx;
  728. margin-top: 60rpx;
  729. margin-bottom: 180rpx;
  730. padding: 0 30rpx;
  731. position: relative;
  732. border-radius: 16rpx;
  733. .left-time{
  734. position: absolute;
  735. bottom: 20rpx;
  736. left: 100rpx;
  737. color: #999999;
  738. font-size: 20rpx;
  739. }
  740. .right-time{
  741. position: absolute;
  742. bottom: 20rpx;
  743. right: 40rpx;
  744. color: #999999;
  745. font-size: 20rpx;
  746. }
  747. image{
  748. width: 40rpx;
  749. height: 48rpx;
  750. flex-shrink: 0;
  751. margin-right: 30rpx;
  752. }
  753. .slider{
  754. flex: 1;
  755. margin: 0 10rpx;
  756. }
  757. .del-btn{
  758. display: flex;
  759. align-items: center;
  760. color: #999999;
  761. font-size: 28rpx;
  762. position: absolute;
  763. bottom: -50rpx;
  764. right: 0;
  765. image{
  766. width: 32rpx;
  767. height: 35rpx;
  768. margin-right: 10rpx;
  769. }
  770. }
  771. .pre_publish_time{
  772. position: absolute;
  773. bottom: -50rpx;
  774. left: 0;
  775. color: #999999;
  776. }
  777. }
  778. .publish-btn{
  779. // width: 390rpx;
  780. // height: 80rpx;
  781. // text-align: center;
  782. // line-height: 80rpx;
  783. // color: #fff;
  784. // background: #E6B77D;
  785. // font-size: 32rpx;
  786. // border-radius: 40px;
  787. // margin-left: auto;
  788. // margin-right: auto;
  789. text-align: center;
  790. text{
  791. width: 300rpx;
  792. height: 80rpx;
  793. text-align: center;
  794. line-height: 80rpx;
  795. display: inline-block;
  796. font-size: 32rpx;
  797. margin: 0 15rpx;
  798. border-radius: 40rpx;
  799. }
  800. text:first-child{
  801. border: 1px solid #E6B77D;
  802. color: #E6B77D;
  803. }
  804. text:last-child{
  805. background-color: #E6B77D;
  806. color: #fff;
  807. }
  808. }
  809. .upload-img-box{
  810. padding: 34rpx 4rpx 34rpx 34rpx;
  811. flex-wrap: wrap;
  812. height: 50vh;
  813. align-content: flex-start;
  814. .item{
  815. width: 200rpx;
  816. height: 200rpx;
  817. margin-right: 30rpx;
  818. margin-bottom: 30rpx;
  819. flex-shrink: 0;
  820. position: relative;
  821. image{
  822. width: 100%;
  823. height: 100%;
  824. }
  825. .del-btn{
  826. position: absolute;
  827. right: 0;
  828. top: 0;
  829. width: 48rpx;
  830. height: 48rpx;
  831. background-color: rgba(0, 0, 0, 0.7);
  832. border-radius: 0 0 0 48rpx;
  833. }
  834. }
  835. .add-btn{
  836. background-color: #f7f7f7;
  837. image{
  838. width: 80rpx;
  839. height: 80rpx;
  840. position: absolute;
  841. left: 60rpx;
  842. top: 60rpx;
  843. }
  844. }
  845. }
  846. }
  847. .animat-box{
  848. height: 50vh;
  849. .con-box{
  850. height: 80%;
  851. background-color: #FAFAFA;
  852. position: relative;
  853. }
  854. .bot-text{
  855. font-size: 60rpx;
  856. padding-top: 36rpx;
  857. text-align: center;
  858. }
  859. .img{
  860. position: absolute;
  861. width: 100vw;
  862. top: 27%;
  863. transform: translateX(100vw);
  864. }
  865. .move1{
  866. animation: move 30s linear infinite;
  867. }
  868. .move2{
  869. animation: move 30s 10s linear infinite;
  870. }
  871. .move3{
  872. animation: move 30s 20s linear infinite;
  873. }
  874. .animat-pause{
  875. animation-play-state: paused;
  876. }
  877. .animat-run{
  878. animation-play-state: running;
  879. }
  880. @keyframes move {
  881. 0%{
  882. transform: translateX(100vw);
  883. }
  884. 100%{
  885. transform: translateX(-200vw);
  886. }
  887. }
  888. }
  889. </style>