|
@@ -1,310 +1,313 @@
|
|
|
-import {
|
|
|
- defineComponent,
|
|
|
- reactive,
|
|
|
- ref,
|
|
|
- nextTick,
|
|
|
- onMounted,
|
|
|
- watch
|
|
|
-} from 'vue';
|
|
|
-import styles from './audio.module.less';
|
|
|
-import iconplay from '../image/icon-pause.png';
|
|
|
-import iconpause from '../image/icon-play.png';
|
|
|
-import iconReplay from '../image/icon-replay.png';
|
|
|
-import { NSlider } from 'naive-ui';
|
|
|
-import Vudio from 'vudio.js';
|
|
|
-import tickMp3 from '../image/tick.mp3';
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'audio-play',
|
|
|
- props: {
|
|
|
- item: {
|
|
|
- type: Object,
|
|
|
- default: () => {
|
|
|
- return {};
|
|
|
- }
|
|
|
- },
|
|
|
- activeStatus: {
|
|
|
- type: Boolean,
|
|
|
- default: false
|
|
|
- },
|
|
|
- isEmtry: {
|
|
|
- type: Boolean,
|
|
|
- default: false
|
|
|
- },
|
|
|
- imagePos: {
|
|
|
- type: String,
|
|
|
- default: 'left'
|
|
|
- }
|
|
|
- },
|
|
|
- emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset'],
|
|
|
- setup(props, { emit, expose }) {
|
|
|
- const audioForms = reactive({
|
|
|
- paused: true,
|
|
|
- currentTimeNum: 0,
|
|
|
- currentTime: '00:00',
|
|
|
- durationNum: 0,
|
|
|
- duration: '00:00',
|
|
|
- showBar: true,
|
|
|
- afterMa3: true,
|
|
|
- count: 0
|
|
|
- });
|
|
|
- const canvas: any = ref();
|
|
|
- const audio: any = ref();
|
|
|
- let vudio: any = null;
|
|
|
-
|
|
|
- // 切换音频播放
|
|
|
- const onToggleAudio = (e?: any) => {
|
|
|
- e?.stopPropagation();
|
|
|
- // console.log(audio.value.paused, 'audio.value.paused');
|
|
|
- if (audio.value.paused) {
|
|
|
- audio.value.play();
|
|
|
- audioForms.afterMa3 = false;
|
|
|
- } else {
|
|
|
- audio.value?.pause();
|
|
|
- }
|
|
|
- audioForms.paused = audio.value?.paused;
|
|
|
- e?.target?.focus();
|
|
|
- emit('togglePlay', audioForms.paused);
|
|
|
- };
|
|
|
-
|
|
|
- const onInit = (audio: undefined, canvas: undefined) => {
|
|
|
- if (!vudio) {
|
|
|
- vudio = new Vudio(audio, canvas, {
|
|
|
- effect: 'waveform',
|
|
|
- accuracy: 256,
|
|
|
- width: 1024,
|
|
|
- height: 600,
|
|
|
- waveform: {
|
|
|
- maxHeight: 200,
|
|
|
- color: [
|
|
|
- [0, '#44D1FF'],
|
|
|
- [0.5, '#44D1FF'],
|
|
|
- [0.5, '#198CFE'],
|
|
|
- [1, '#198CFE']
|
|
|
- ],
|
|
|
- prettify: false
|
|
|
- }
|
|
|
- });
|
|
|
- vudio.dance();
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 对时间进行格式化
|
|
|
- const timeFormat = (num: number) => {
|
|
|
- if (num > 0) {
|
|
|
- const m = Math.floor(num / 60);
|
|
|
- const s = num % 60;
|
|
|
- return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
|
|
- } else {
|
|
|
- return '00:00';
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- //
|
|
|
- const toggleHideControl = (isShow: false) => {
|
|
|
- audioForms.showBar = isShow;
|
|
|
- };
|
|
|
-
|
|
|
- const onReplay = () => {
|
|
|
- if (!audio.value) return;
|
|
|
- audio.value.currentTime = 0;
|
|
|
- };
|
|
|
-
|
|
|
- let vudio1 = null;
|
|
|
- const canvas1: any = ref();
|
|
|
- const audio1: any = ref();
|
|
|
- nextTick(() => {
|
|
|
- vudio1 = new Vudio(audio1.value, canvas1.value, {
|
|
|
- effect: 'waveform',
|
|
|
- accuracy: 256,
|
|
|
- width: 1024,
|
|
|
- height: 600,
|
|
|
- waveform: {
|
|
|
- maxHeight: 200,
|
|
|
- color: [
|
|
|
- [0, '#44D1FF'],
|
|
|
- [0.5, '#44D1FF'],
|
|
|
- [0.5, '#198CFE'],
|
|
|
- [1, '#198CFE']
|
|
|
- ],
|
|
|
- prettify: false
|
|
|
- }
|
|
|
- });
|
|
|
- vudio1.dance();
|
|
|
- });
|
|
|
-
|
|
|
- watch(
|
|
|
- () => props.activeStatus,
|
|
|
- (val: any) => {
|
|
|
- // console.log(val, 'val');
|
|
|
- audioForms.count = 0;
|
|
|
- if (val && props.item.autoPlay) {
|
|
|
- vudio = null;
|
|
|
- onToggleAudio();
|
|
|
- } else {
|
|
|
- audio.value.pause();
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- // onMounted(() => {
|
|
|
- // console.log(props.item, 'eeeee');
|
|
|
- // });
|
|
|
-
|
|
|
- expose({
|
|
|
- toggleHideControl
|
|
|
- });
|
|
|
-
|
|
|
- return () => (
|
|
|
- <div class={styles.audioWrap}>
|
|
|
- <div class={styles.audioContainer}>
|
|
|
- <audio
|
|
|
- ref={audio}
|
|
|
- crossorigin="anonymous"
|
|
|
- src={props.item.content + '?time=1'}
|
|
|
- onEnded={() => {
|
|
|
- audioForms.paused = true;
|
|
|
- emit('ended');
|
|
|
- }}
|
|
|
- onTimeupdate={() => {
|
|
|
- audioForms.currentTime = timeFormat(
|
|
|
- Math.round(audio.value?.currentTime || 0)
|
|
|
- );
|
|
|
- audioForms.currentTimeNum = audio.value?.currentTime || 0;
|
|
|
-
|
|
|
- if (audioForms.count <= 1) {
|
|
|
- audioForms.count += 1;
|
|
|
- onInit(audio.value, canvas.value);
|
|
|
- }
|
|
|
- }}
|
|
|
- onLoadedmetadata={() => {
|
|
|
- audioForms.duration = timeFormat(
|
|
|
- Math.round(audio.value?.duration)
|
|
|
- );
|
|
|
- audioForms.durationNum = audio.value?.duration;
|
|
|
-
|
|
|
- if (props.item.autoPlay && audio.value && props.activeStatus) {
|
|
|
- // audio.value.play();
|
|
|
- onToggleAudio();
|
|
|
- }
|
|
|
- if (audio.value) {
|
|
|
- audio.value.stop = () => {
|
|
|
- audio.value?.pause();
|
|
|
- audioForms.paused = true;
|
|
|
- emit('togglePlay', audioForms.paused);
|
|
|
- };
|
|
|
- audio.value.onPlay = () => {
|
|
|
- audio.value?.play();
|
|
|
- audioForms.paused = false;
|
|
|
- onInit(audio.value, canvas.value);
|
|
|
- emit('togglePlay', audioForms.paused);
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- emit('loadedmetadata', audio.value);
|
|
|
- }}></audio>
|
|
|
-
|
|
|
- <canvas ref={canvas}></canvas>
|
|
|
-
|
|
|
- {audioForms.afterMa3 && (
|
|
|
- <div class={styles.tempVudio}>
|
|
|
- <audio ref={audio1} src={tickMp3} />
|
|
|
- <canvas ref={canvas1}></canvas>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.controls,
|
|
|
- audioForms.showBar ? '' : styles.sectionAnimate
|
|
|
- ]}
|
|
|
- onClick={(e: MouseEvent) => {
|
|
|
- e.stopPropagation();
|
|
|
- emit('reset');
|
|
|
- }}>
|
|
|
- <div class={styles.slider}>
|
|
|
- <NSlider
|
|
|
- value={audioForms.currentTimeNum}
|
|
|
- step={0.01}
|
|
|
- max={audioForms.durationNum}
|
|
|
- tooltip={false}
|
|
|
- onUpdate:value={(val: number) => {
|
|
|
- audio.value.currentTime = val;
|
|
|
- audioForms.currentTimeNum = val;
|
|
|
- audioForms.currentTime = timeFormat(Math.round(val || 0));
|
|
|
- }}
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class={styles.tools}>
|
|
|
- {props.imagePos === 'right' ? (
|
|
|
- <>
|
|
|
- <div class={styles.actions}>
|
|
|
- <div class={styles.time}>
|
|
|
- <div
|
|
|
- class="plyr__time plyr__time--current"
|
|
|
- aria-label="Current time">
|
|
|
- {audioForms.currentTime}
|
|
|
- </div>
|
|
|
- <span class={styles.line}>/</span>
|
|
|
- <div
|
|
|
- class="plyr__time plyr__time--duration"
|
|
|
- aria-label="Duration">
|
|
|
- {audioForms.duration}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class={styles.actions}>
|
|
|
- <div class={styles.actionWrap}>
|
|
|
- <button class={styles.iconReplay} onClick={onReplay}>
|
|
|
- <img src={iconReplay} />
|
|
|
- </button>
|
|
|
- <div class={styles.actionBtn} onClick={onToggleAudio}>
|
|
|
- {audioForms.paused ? (
|
|
|
- <img class={styles.playIcon} src={iconplay} />
|
|
|
- ) : (
|
|
|
- <img class={styles.playIcon} src={iconpause} />
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </>
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- <div class={styles.actions}>
|
|
|
- <div class={styles.actionWrap}>
|
|
|
- <div class={styles.actionBtn} onClick={onToggleAudio}>
|
|
|
- {audioForms.paused ? (
|
|
|
- <img class={styles.playIcon} src={iconplay} />
|
|
|
- ) : (
|
|
|
- <img class={styles.playIcon} src={iconpause} />
|
|
|
- )}
|
|
|
- </div>
|
|
|
- <button class={styles.iconReplay} onClick={onReplay}>
|
|
|
- <img src={iconReplay} />
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class={styles.actions}>
|
|
|
- <div class={styles.time}>
|
|
|
- <div
|
|
|
- class="plyr__time plyr__time--current"
|
|
|
- aria-label="Current time">
|
|
|
- {audioForms.currentTime}
|
|
|
- </div>
|
|
|
- <span class={styles.line}>/</span>
|
|
|
- <div
|
|
|
- class="plyr__time plyr__time--duration"
|
|
|
- aria-label="Duration">
|
|
|
- {audioForms.duration}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-});
|
|
|
+import {
|
|
|
+ defineComponent,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ nextTick,
|
|
|
+ onMounted,
|
|
|
+ watch
|
|
|
+} from 'vue';
|
|
|
+import styles from './audio.module.less';
|
|
|
+import iconplay from '../image/icon-pause.png';
|
|
|
+import iconpause from '../image/icon-play.png';
|
|
|
+import iconReplay from '../image/icon-replay.png';
|
|
|
+import { NSlider } from 'naive-ui';
|
|
|
+import Vudio from 'vudio.js';
|
|
|
+import tickMp3 from '../image/tick.mp3';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'audio-play',
|
|
|
+ props: {
|
|
|
+ item: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ },
|
|
|
+ activeStatus: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ isEmtry: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ imagePos: {
|
|
|
+ type: String,
|
|
|
+ default: 'left'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset'],
|
|
|
+ setup(props, { emit, expose }) {
|
|
|
+ const audioForms = reactive({
|
|
|
+ paused: true,
|
|
|
+ currentTimeNum: 0,
|
|
|
+ currentTime: '00:00',
|
|
|
+ durationNum: 0,
|
|
|
+ duration: '00:00',
|
|
|
+ showBar: true,
|
|
|
+ afterMa3: true,
|
|
|
+ count: 0
|
|
|
+ });
|
|
|
+ const canvas: any = ref();
|
|
|
+ const audio: any = ref();
|
|
|
+ let vudio: any = null;
|
|
|
+
|
|
|
+ // 切换音频播放
|
|
|
+ const onToggleAudio = (e?: any) => {
|
|
|
+ e?.stopPropagation();
|
|
|
+ // console.log(audio.value.paused, 'audio.value.paused');
|
|
|
+ if (audio.value.paused) {
|
|
|
+ audio.value.play();
|
|
|
+ audioForms.afterMa3 = false;
|
|
|
+ } else {
|
|
|
+ audio.value?.pause();
|
|
|
+ }
|
|
|
+ audioForms.paused = audio.value?.paused;
|
|
|
+ e?.target?.focus();
|
|
|
+ emit('togglePlay', audioForms.paused);
|
|
|
+ };
|
|
|
+
|
|
|
+ const onInit = (audio: undefined, canvas: undefined) => {
|
|
|
+ if (!vudio) {
|
|
|
+ vudio = new Vudio(audio, canvas, {
|
|
|
+ effect: 'waveform',
|
|
|
+ accuracy: 256,
|
|
|
+ width: 1024,
|
|
|
+ height: 600,
|
|
|
+ waveform: {
|
|
|
+ maxHeight: 200,
|
|
|
+ color: [
|
|
|
+ [0, '#44D1FF'],
|
|
|
+ [0.5, '#44D1FF'],
|
|
|
+ [0.5, '#198CFE'],
|
|
|
+ [1, '#198CFE']
|
|
|
+ ],
|
|
|
+ prettify: false
|
|
|
+ }
|
|
|
+ });
|
|
|
+ vudio.dance();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 对时间进行格式化
|
|
|
+ const timeFormat = (num: number) => {
|
|
|
+ if (num > 0) {
|
|
|
+ const m = Math.floor(num / 60);
|
|
|
+ const s = num % 60;
|
|
|
+ return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
|
|
+ } else {
|
|
|
+ return '00:00';
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ //
|
|
|
+ const toggleHideControl = (isShow: false) => {
|
|
|
+ audioForms.showBar = isShow;
|
|
|
+ };
|
|
|
+
|
|
|
+ const onReplay = () => {
|
|
|
+ if (!audio.value) return;
|
|
|
+ audio.value.currentTime = 0;
|
|
|
+ };
|
|
|
+
|
|
|
+ let vudio1 = null;
|
|
|
+ const canvas1: any = ref();
|
|
|
+ const audio1: any = ref();
|
|
|
+ nextTick(() => {
|
|
|
+ vudio1 = new Vudio(audio1.value, canvas1.value, {
|
|
|
+ effect: 'waveform',
|
|
|
+ accuracy: 256,
|
|
|
+ width: 1024,
|
|
|
+ height: 600,
|
|
|
+ waveform: {
|
|
|
+ maxHeight: 200,
|
|
|
+ color: [
|
|
|
+ [0, '#44D1FF'],
|
|
|
+ [0.5, '#44D1FF'],
|
|
|
+ [0.5, '#198CFE'],
|
|
|
+ [1, '#198CFE']
|
|
|
+ ],
|
|
|
+ prettify: false
|
|
|
+ }
|
|
|
+ });
|
|
|
+ vudio1.dance();
|
|
|
+ });
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.activeStatus,
|
|
|
+ (val: any) => {
|
|
|
+ // console.log(val, 'val');
|
|
|
+ audioForms.count = 0;
|
|
|
+ if (val && props.item.autoPlay) {
|
|
|
+ vudio = null;
|
|
|
+ onToggleAudio();
|
|
|
+ } else {
|
|
|
+ audio.value.pause();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ // onMounted(() => {
|
|
|
+ // console.log(props.item, 'eeeee');
|
|
|
+ // });
|
|
|
+
|
|
|
+ expose({
|
|
|
+ toggleHideControl
|
|
|
+ });
|
|
|
+
|
|
|
+ return () => (
|
|
|
+ <div class={styles.audioWrap}>
|
|
|
+ <div class={styles.audioContainer}>
|
|
|
+ <audio
|
|
|
+ ref={audio}
|
|
|
+ crossorigin="anonymous"
|
|
|
+ src={props.item.content + '?time=1'}
|
|
|
+ onEnded={() => {
|
|
|
+ audioForms.paused = true;
|
|
|
+ emit('ended');
|
|
|
+ }}
|
|
|
+ onTimeupdate={() => {
|
|
|
+ audioForms.currentTime = timeFormat(
|
|
|
+ Math.round(audio.value?.currentTime || 0)
|
|
|
+ );
|
|
|
+ audioForms.currentTimeNum = audio.value?.currentTime || 0;
|
|
|
+
|
|
|
+ if (audioForms.count <= 1) {
|
|
|
+ audioForms.count += 1;
|
|
|
+ onInit(audio.value, canvas.value);
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onLoadedmetadata={() => {
|
|
|
+ audioForms.duration = timeFormat(
|
|
|
+ Math.round(audio.value?.duration)
|
|
|
+ );
|
|
|
+ audioForms.durationNum = audio.value?.duration;
|
|
|
+
|
|
|
+ if (props.item.autoPlay && audio.value && props.activeStatus) {
|
|
|
+ // audio.value.play();
|
|
|
+ onToggleAudio();
|
|
|
+ }
|
|
|
+ if (audio.value) {
|
|
|
+ audio.value.stop = () => {
|
|
|
+ audio.value?.pause();
|
|
|
+ audioForms.paused = true;
|
|
|
+ emit('togglePlay', audioForms.paused);
|
|
|
+ };
|
|
|
+ audio.value.onPlay = () => {
|
|
|
+ audio.value?.play();
|
|
|
+ audioForms.paused = false;
|
|
|
+ onInit(audio.value, canvas.value);
|
|
|
+ emit('togglePlay', audioForms.paused);
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ emit('loadedmetadata', audio.value);
|
|
|
+ }}
|
|
|
+ onProgress={(e: any) => {
|
|
|
+ console.log(e, 'loadedmetadata onProgress');
|
|
|
+ }}></audio>
|
|
|
+
|
|
|
+ <canvas ref={canvas}></canvas>
|
|
|
+
|
|
|
+ {audioForms.afterMa3 && (
|
|
|
+ <div class={styles.tempVudio}>
|
|
|
+ <audio ref={audio1} src={tickMp3} />
|
|
|
+ <canvas ref={canvas1}></canvas>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.controls,
|
|
|
+ audioForms.showBar ? '' : styles.sectionAnimate
|
|
|
+ ]}
|
|
|
+ onClick={(e: MouseEvent) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ emit('reset');
|
|
|
+ }}>
|
|
|
+ <div class={styles.slider}>
|
|
|
+ <NSlider
|
|
|
+ value={audioForms.currentTimeNum}
|
|
|
+ step={0.01}
|
|
|
+ max={audioForms.durationNum}
|
|
|
+ tooltip={false}
|
|
|
+ onUpdate:value={(val: number) => {
|
|
|
+ audio.value.currentTime = val;
|
|
|
+ audioForms.currentTimeNum = val;
|
|
|
+ audioForms.currentTime = timeFormat(Math.round(val || 0));
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class={styles.tools}>
|
|
|
+ {props.imagePos === 'right' ? (
|
|
|
+ <>
|
|
|
+ <div class={styles.actions}>
|
|
|
+ <div class={styles.time}>
|
|
|
+ <div
|
|
|
+ class="plyr__time plyr__time--current"
|
|
|
+ aria-label="Current time">
|
|
|
+ {audioForms.currentTime}
|
|
|
+ </div>
|
|
|
+ <span class={styles.line}>/</span>
|
|
|
+ <div
|
|
|
+ class="plyr__time plyr__time--duration"
|
|
|
+ aria-label="Duration">
|
|
|
+ {audioForms.duration}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.actions}>
|
|
|
+ <div class={styles.actionWrap}>
|
|
|
+ <button class={styles.iconReplay} onClick={onReplay}>
|
|
|
+ <img src={iconReplay} />
|
|
|
+ </button>
|
|
|
+ <div class={styles.actionBtn} onClick={onToggleAudio}>
|
|
|
+ {audioForms.paused ? (
|
|
|
+ <img class={styles.playIcon} src={iconplay} />
|
|
|
+ ) : (
|
|
|
+ <img class={styles.playIcon} src={iconpause} />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <div class={styles.actions}>
|
|
|
+ <div class={styles.actionWrap}>
|
|
|
+ <div class={styles.actionBtn} onClick={onToggleAudio}>
|
|
|
+ {audioForms.paused ? (
|
|
|
+ <img class={styles.playIcon} src={iconplay} />
|
|
|
+ ) : (
|
|
|
+ <img class={styles.playIcon} src={iconpause} />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ <button class={styles.iconReplay} onClick={onReplay}>
|
|
|
+ <img src={iconReplay} />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.actions}>
|
|
|
+ <div class={styles.time}>
|
|
|
+ <div
|
|
|
+ class="plyr__time plyr__time--current"
|
|
|
+ aria-label="Current time">
|
|
|
+ {audioForms.currentTime}
|
|
|
+ </div>
|
|
|
+ <span class={styles.line}>/</span>
|
|
|
+ <div
|
|
|
+ class="plyr__time plyr__time--duration"
|
|
|
+ aria-label="Duration">
|
|
|
+ {audioForms.duration}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|