@94ai/nf-audio 3.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,286 @@
1
+ <template>
2
+ <div class="nf-audio-strip">
3
+ <audio @canplay="getDuration" controls crossOrigin="anonymous" @timeupdate="updateTime" @ended="handleAudioEnded" v-show="false" ref="audio"
4
+ :src="audioSrc"/>
5
+ <div class="nf-fast">
6
+ <i class="iconfont icon-zanting1 nf-fast-icon" @click="jumpToTime" />
7
+ <!-- 以下是 快进/快退 功能 -->
8
+ <!--
9
+ <div>
10
+ <span class="pre" @click="handleBack">
11
+ <i class="el-icon-d-arrow-left"></i>
12
+ <span style="color: #C7C7C9;font-size: 13px;margin-left: 10px">-{{ backSecond }}s</span>
13
+ </span>
14
+ <span style="display:inline-block; height: 20px; width: 100px;"></span>
15
+ <span class="next" @click="handleForward">
16
+ <span style="color: #C7C7C9;font-size: 13px;margin-right: 10px">+{{ forwardSecond }}s </span>
17
+ <i class="el-icon-d-arrow-right"></i>
18
+ </span>
19
+ </div>
20
+ -->
21
+ </div>
22
+ <div class="nf-audio">
23
+ <div class="play" @click="handlePauseOrPlay">
24
+ <i class="iconfont icon-zanting2 pause-icon" v-show="!paused"/>
25
+ <i class="iconfont icon-bofang1 play-icon" v-show="paused"/>
26
+ </div>
27
+ <div class="time">
28
+ <span class="startTime">{{ currentDuration }}</span>/
29
+ <span class="endTime">{{ duration }}</span>
30
+ </div>
31
+ <div class="progress" ref="progress" @click="clickProgress" @mouseup="handleMouseup">
32
+ <div class="currentProgress" ref="currentProgress">
33
+ <span class="circle" ref="circle" @mousedown="handleMousedown"></span>
34
+ </div>
35
+ </div>
36
+ <div class="nf-volume-panel">
37
+ <volumeTool :visible.sync="volumeVisible">
38
+ <template v-slot:reference>
39
+ <i class="iconfont icon-yinliang_guanbi volume-mute" v-if="volume == 0" />
40
+ <i class="iconfont icon-yinliang_kaiqi volume" v-else/>
41
+ </template>
42
+ <el-slider
43
+ v-model="volumeValue"
44
+ vertical
45
+ :min="0"
46
+ :max="100"
47
+ :show-tooltip="volumeVisible"
48
+ :class="volumeValue===0 ? 'volume-mute-slider' : 'volume-phonic'"
49
+ @change="rangeVolume"
50
+ height="60px">
51
+ </el-slider>
52
+ </volumeTool>
53
+ </div>
54
+ <div class="option">
55
+ <moreBtn @down="downRecord()" @speed="changeSpeed" />
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </template>
60
+
61
+ <script>
62
+ import volumeTool from './volume-tool.vue'
63
+ import moreBtn from './more-btn.vue'
64
+ import { Message } from 'element-ui'
65
+
66
+ export default {
67
+ name: "nf-audio",
68
+ components: { volumeTool, moreBtn },
69
+ props: {
70
+ audioSrc: {
71
+ type: String,
72
+ default: ''
73
+ },
74
+ backSecond: {
75
+ type: Number,
76
+ default: 3
77
+ },
78
+ forwardSecond: {
79
+ type: Number,
80
+ default: 10
81
+ },
82
+ startTime: {
83
+ type: Number,
84
+ default: 0
85
+ }
86
+ },
87
+ data() {
88
+ return {
89
+ duration: '00:00',
90
+ currentDuration: '00:00',
91
+ audio: '',
92
+ volume: 0.8,
93
+ paused: true,
94
+ showVolumePanel: false,
95
+ volumeVisible: false,
96
+ volumeValue: 80,
97
+ speed: 1.0
98
+ }
99
+ },
100
+ mounted() {
101
+ this.audio = this.$refs.audio
102
+ },
103
+ methods: {
104
+ //后退
105
+ handleBack() {
106
+ if (this.audio.currentTime > this.backSecond) {
107
+ this.audio.currentTime = this.audio.currentTime - this.backSecond
108
+ }
109
+ },
110
+ //前进
111
+ handleForward() {
112
+ if (this.audio.duration - this.audio.currentTime > this.forwardSecond) {
113
+ this.audio.currentTime = this.audio.currentTime + 10
114
+ }
115
+ },
116
+ //暂停或播放
117
+ handlePauseOrPlay() {
118
+ if (this.audio.readyState >= 2) {
119
+ // 如果音频资源已加载元数据或更多,可以播放
120
+ this.audio.paused ? this.audio.play() : this.audio.pause()
121
+ this.audio.playbackRate = this.speed
122
+ this.paused = !this.paused
123
+ } else {
124
+ console.log("Audio is not ready yet.");
125
+ Message.warning("音频还未加载完成")
126
+ }
127
+ },
128
+ //视频在可以播放时触发
129
+ getDuration() {
130
+ this.duration = this.timeFormat(this.$refs.audio.duration)
131
+ this.audio.volume = this.volume //默认百分百音量
132
+ //监听音量的变化
133
+ // this.audio.addEventListener('volumechange',(volumeValue)=>{
134
+ // console.log(this.audio.volume)
135
+ // })
136
+ },
137
+ //将单位为秒的的时间转换成mm:ss的形式
138
+ timeFormat( number ) {
139
+ let minute = parseInt(number / 60);
140
+ let second = parseInt(number % 60);
141
+ minute = minute >= 10 ? minute : "0" + minute;
142
+ second = second >= 10 ? second : "0" + second;
143
+ return minute + ":" + second;
144
+ },
145
+ //进度条发生变化时触发
146
+ updateTime() {
147
+ if (!this.$refs.progress) return
148
+ this.currentDuration = this.timeFormat(this.audio.currentTime)
149
+ //如果不是正在移动 和 没有暂停播放就执行
150
+ if ( !this.audio.paused) {
151
+ // 设置当前时间
152
+ let MoveX = this.$refs.progress.clientWidth * ( this.audio.currentTime / this.audio.duration )
153
+ //播放时更新距离
154
+ this.$refs.currentProgress.style.width = MoveX + 'px'
155
+ this.$refs.circle.style.left = MoveX - ( this.$refs.circle.clientWidth / 2 ) + 'px'
156
+ this.paused = false
157
+ }
158
+ },
159
+ handleAudioEnded(){
160
+ // 在这里处理音频播放完毕的逻辑
161
+ console.log('音频播放完毕!');
162
+ this.paused = true
163
+ },
164
+ //点击进度条更新进度
165
+ clickProgress( e ) {
166
+ if(this.duration === '00:00'){
167
+ Message.warning("音频还未加载完成")
168
+ return false
169
+ }
170
+ //如果不是正在移动 和 没有暂停播放就执行
171
+ if (!this.audio.paused) {
172
+ this.updateProgress(e.offsetX)
173
+ }
174
+ },
175
+ //更新进度
176
+ updateProgress( MoveX ) {
177
+ //当前移动的位置 = 当前移动的位置 / 当前进度条的可视长度 //this.$refs.progress.clientWidth 注意一定要拿总长度 否则会拿进度条已经走过的长度
178
+ let clickProgress = ( MoveX / this.$refs.progress.clientWidth )
179
+ //设置播放的时间 = 总时长 * 当前点击的长度
180
+ this.audio.currentTime = this.audio.duration * clickProgress
181
+ //设置移动的位置
182
+ this.$refs.currentProgress.style.width = MoveX + 'px'
183
+ this.$refs.circle.style.left = MoveX - ( this.$refs.circle.clientWidth / 2 ) + 'px'
184
+ },
185
+ //鼠标弹起
186
+ handleMouseup() {
187
+ if(this.duration === '00:00'){
188
+ Message.warning("音频还未加载完成")
189
+ return false
190
+ }
191
+ // 销毁的时候清除定时器
192
+ const timer = setTimeout(() => {
193
+ this.audio.play()
194
+ this.paused = false
195
+ clearTimeout(timer)
196
+ }, 200)
197
+
198
+ this.$once('hook:beforeDestroy', () => {
199
+ clearTimeout(timer)
200
+ })
201
+ },
202
+ //调整进度
203
+ handleMousedown() {
204
+ this.audio.pause()
205
+ this.paused = true
206
+ let progress = this.$refs.progress
207
+ //进度条 左 边距离页面左边的距离 移动最小值
208
+ let moveMin = progress.offsetParent.offsetLeft + progress.offsetLeft
209
+ //进度条 右 边距离页面左边的距离 移动最大值
210
+ let moveMax = progress.offsetParent.offsetLeft + progress.offsetLeft + progress.clientWidth
211
+ //小圆圈的宽度
212
+ let circleWidth = ( this.$refs.circle.clientWidth / 2 )
213
+ let moveX = ( e ) => {
214
+ if (e.pageX >= moveMax) {
215
+ return
216
+ } else if (e.pageX <= moveMin) {
217
+ return
218
+ }
219
+ this.$refs.circle.style.left = e.pageX - moveMin - circleWidth + 'px'
220
+ this.updateProgress(e.pageX - moveMin)
221
+ }
222
+ //获取当前鼠标的位置 X
223
+ document.addEventListener('mousemove', moveX)
224
+ //鼠标弹起来
225
+ document.addEventListener('mouseup', () => {
226
+ document.removeEventListener('mousemove', moveX)
227
+ })
228
+ },
229
+ rangeVolume(val){
230
+ console.log(val);
231
+ },
232
+ /** 设置倍速播放 */
233
+ changeSpeed(command) {
234
+ const audioPlayer = this.$refs.audio
235
+ if (audioPlayer) {
236
+ audioPlayer.playbackRate = command
237
+ }
238
+ this.speed = command
239
+ },
240
+ downRecord() {
241
+ this.$emit('downloadCallback')
242
+ },
243
+ calcMoveX() {
244
+ if (!this.audio.paused) {
245
+ // 设置当前时间
246
+ let MoveX = this.$refs.progress.clientWidth * ( this.audio.currentTime / this.audio.duration )
247
+ //播放时更新距离
248
+ this.$refs.currentProgress.style.width = MoveX + 'px'
249
+ this.$refs.circle.style.left = MoveX - ( this.$refs.circle.clientWidth / 2 ) + 'px'
250
+ }
251
+ },
252
+ jumpToTime(){
253
+ this.audio.pause()
254
+ const formatStartT = this.timeFormat(this.startTime)
255
+ if(this.duration === '00:00'){
256
+ Message.warning("音频还未加载完成")
257
+ return false
258
+ }
259
+ if(formatStartT >= this.duration){
260
+ this.audio.currentTime = this.duration
261
+ this.currentDuration = this.timeFormat(this.audio.currentTime)
262
+ this.calcMoveX()
263
+ this.audio.play()
264
+ console.error("开始时间不能大于总时长");
265
+ return false
266
+ }else if(formatStartT >= '00:00' && formatStartT < this.duration){
267
+ this.audio.currentTime = this.startTime
268
+ this.currentDuration = this.timeFormat(this.audio.currentTime)
269
+ this.calcMoveX()
270
+ this.audio.play()
271
+ }else{
272
+ this.audio.currentTime = 0
273
+ this.currentDuration = this.timeFormat(this.audio.currentTime)
274
+ this.calcMoveX()
275
+ this.audio.play()
276
+ }
277
+ }
278
+ },
279
+ watch:{
280
+ volumeValue(val){
281
+ this.volume = val/100
282
+ this.audio.volume = val/100
283
+ }
284
+ }
285
+ }
286
+ </script>
@@ -0,0 +1 @@
1
+ import '@94ai/nf-theme-chalk/lib/css/nf-audio.css'
@@ -0,0 +1 @@
1
+ import '@94ai/nf-theme-chalk/lib/nf-audio.scss'
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <div class="nf-volume-tool" :class=" visible ? 'nf-tool-show':'nf-tool-hide'" @click="showPopper" >
3
+ <div ref="reference">
4
+ <slot name="reference"/>
5
+ </div>
6
+ <transition name="slide-fade">
7
+ <div ref="popperRef" class="nf-popper" v-show="visible" >
8
+ <slot/>
9
+ </div>
10
+ </transition>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup>
15
+ import { watch, ref ,onUnmounted} from 'vue-demi'
16
+
17
+ const emits = defineEmits(['update:visible'])
18
+ const props = defineProps({
19
+ visible: [Boolean, String]
20
+ })
21
+ const reference = ref()
22
+ const popperRef = ref()
23
+
24
+ watch(() => props.visible, ( newValue ) => {
25
+ if (newValue) {
26
+ window.addEventListener('mousedown',docClick)
27
+ }else {
28
+ window.removeEventListener('mousedown',docClick)
29
+ }
30
+ })
31
+
32
+ function docClick(e){
33
+ //如果点击的是音量 或者 是音量面板 则 不隐藏音量面板
34
+ if (popperRef.value.contains(e.target) || reference.value.contains(e.target)){
35
+ return
36
+ }
37
+ emits('update:visible', false)
38
+ }
39
+
40
+ function showPopper() {
41
+ emits('update:visible', true)
42
+ }
43
+
44
+ onUnmounted(()=>{
45
+ emits('update:visible', false)
46
+ })
47
+ defineExpose({
48
+ showPopper
49
+ })
50
+ </script>
51
+
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@94ai/nf-audio",
3
+ "version": "3.1.13",
4
+ "description": "> TODO: description",
5
+ "keywords": [],
6
+ "author": "liuxiangxiang <liuxiangxiang@94ai.com>",
7
+ "homepage": "https://oss.xccjh.top/common-ui/#/ai-index",
8
+ "license": "ISC",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "http://94ai.gitlab.com/zoujiahe/common-ui.git"
15
+ },
16
+ "dependencies": {
17
+ "@94ai/nf-theme-chalk": "^3.1.13",
18
+ "vue-demi": "^0.14.5"
19
+ },
20
+ "peerDependenciesMeta": {
21
+ "@vue/composition-api": {
22
+ "optional": true
23
+ }
24
+ },
25
+ "peerDependencies": {
26
+ "@vue/composition-api": "^1.0.0-rc.1",
27
+ "element-ui": ">=2.13.2",
28
+ "vue": "^2.0.0 || >=3.0.0"
29
+ },
30
+ "types": "lib/index.d.ts",
31
+ "main": "lib/nf-audio.cjs.js",
32
+ "module": "lib/nf-audio.esm-bundler.js",
33
+ "gitHead": "a8c56183ccc8e979008e2d38bfde2d7d1448654c"
34
+ }
@@ -0,0 +1,8 @@
1
+ export default {
2
+ plugins: {
3
+ // 这个工具可以实现自动添加CSS3前缀
4
+ autoprefixer: {
5
+ overrideBrowserslist: ['last 5 version', '>1%', 'ie >=8']
6
+ },
7
+ },
8
+ }