zydx-plus 1.32.254 → 1.32.255

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zydx-plus",
3
- "version": "1.32.254",
3
+ "version": "1.32.255",
4
4
  "description": "Vue.js",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -104,6 +104,12 @@ export default {
104
104
  // 全局监听鼠标抬起事件
105
105
  document.addEventListener('mouseup', this.mouseup);
106
106
  document.addEventListener('mouseup', this.footUp);
107
+ this.$nextTick(() => {
108
+ this.$emit('updateDrag', {
109
+ width: this.footRightOffset,
110
+ height: this.footDownOffset - ((this.dragTextShow)?60:30)
111
+ })
112
+ })
107
113
  },
108
114
  computed: {
109
115
  position() {
@@ -14,6 +14,11 @@
14
14
  </label>
15
15
  <button v-else class="buts" @click="toolTap(item.key)">{{ item.title }}</button>
16
16
  </div>
17
+ <div class="voice">
18
+ <button class="buts" @click="voice" :style="{color: (voiceStatus)? '#00ff00' :'#000'}">
19
+ {{ voiceStatus ? '关闭语音' : '语音输入' }}
20
+ </button>
21
+ </div>
17
22
  </div>
18
23
  </div>
19
24
  <div class="ed-cont" :style="heightStyleCont">
@@ -75,9 +80,35 @@
75
80
  </div>
76
81
  </div>
77
82
  </div>
83
+ <div class="microphone" v-if="voiceStatus">
84
+ <div class="microphone-cont" :class="{'mic-anim': recordingStatus}">
85
+ <div class="microphone1">
86
+ <div class="microphone2">
87
+ <div class="microphone3" @click.stop="startVoice">
88
+ <svgs :vol="vol"></svgs>
89
+ <p v-if="recordingStatus">{{ voiceLoading? '语音转换中...': `正在说话:${countdown}s` }}</p>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ <div class="microphone-text">{{ recordingStatus?'按下停止说话':'按下开始说话' }}</div>
95
+ </div>
96
+ <div class="text-editing" v-if="textEditing">
97
+ <div class="text-editing-cont">
98
+ <p>语音转换结果:</p>
99
+ <zydx-textarea ref="textarea" :height="130" :value="voiceContent"></zydx-textarea>
100
+ <div class="text-editing-but">
101
+ <button class="buts" @click="editingConfirm">确认</button>
102
+ <button class="buts" @click="editingCancel">取消</button>
103
+ </div>
104
+ </div>
105
+ </div>
78
106
  </div>
79
107
  </template>
80
108
  <script>
109
+ import Recorder from 'js-audio-recorder'
110
+ import axios from 'axios'
111
+ import zydxTextarea from '../../textarea/src/textarea'
81
112
  import {html2json, json2html} from 'html2json'
82
113
  import {Editor, EditorContent} from '@tiptap/vue-3'
83
114
  import StarterKit from '@tiptap/starter-kit'
@@ -89,22 +120,37 @@ import textStyle from '@tiptap/extension-text-style'
89
120
  import {sid} from "./sign-id";
90
121
  import {FontSize} from "./font-size";
91
122
  import {titleId} from "./title-id";
123
+ import svgs from "./microphone";
92
124
 
93
125
  export default {
94
126
  name: 'zydx-xiao-editor',
95
127
  components: {
96
- EditorContent
128
+ EditorContent,
129
+ svgs,
130
+ zydxTextarea
97
131
  },
98
132
  data() {
99
133
  return {
100
134
  uploadAttData: [],
101
135
  editor: null,
102
136
  heightStyle: {},
103
- heightStyleCont: {}
104
- };
137
+ heightStyleCont: {},
138
+ voiceStatus: false,
139
+ recorder: null,
140
+ drawRecordId: null,
141
+ recordingStatus: false,
142
+ countdown: 59,
143
+ fileSize: 0,
144
+ vol: 0,
145
+ base64: '',
146
+ voiceContent: '',
147
+ voiceLoading: false,
148
+ textEditing: false
149
+ }
105
150
  },
106
151
  beforeUnmount() {
107
152
  this.editor.destroy()
153
+ this.recorder.destroy()
108
154
  },
109
155
  props: {
110
156
  data: {
@@ -275,8 +321,124 @@ export default {
275
321
  json.content.splice(index, 1)
276
322
  this.editor?.commands.setContent(json)
277
323
  })
324
+ // 初始化录音
325
+ this.recorder = new Recorder({
326
+ sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
327
+ sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
328
+ numChannels: 1, // 声道,支持 1 或 2, 默认是1
329
+ // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
330
+ })
331
+ this.recorder.onprogress = function (params) {
332
+ if(_this.countdown <= 0) {
333
+ _this.stopRecording()
334
+ }else {
335
+ _this.countdown = 59 - parseInt(params.duration)
336
+ _this.fileSize = params.fileSize
337
+ _this.vol = params.vol
338
+ }
339
+ }
278
340
  },
279
341
  methods: {
342
+ editingConfirm() {
343
+ this.textEditing = false
344
+ const html = this.$refs.textarea.getContent().split('<br>')
345
+ let editorHtml = this.editor.getHTML()
346
+ for(let i=0; i< html.length; i++) {
347
+ editorHtml += `<p>${html[i]}</p>`
348
+ }
349
+ this.editor.commands.setContent(editorHtml)
350
+ },
351
+ editingCancel() {
352
+ this.textEditing = false
353
+ },
354
+ // 语音输入
355
+ voice() {
356
+ this.voiceStatus = !this.voiceStatus
357
+ this.recorder.stop() // 停止录音
358
+ this.recorder.destroy() // 销毁录音
359
+ },
360
+ startVoice() {
361
+ if (!this.recordingStatus) {
362
+ this.recorder.start().then(() => { // 开始录音
363
+ this.fileSize = 0
364
+ this.recordingStatus = true
365
+ }, (error) => {
366
+ this.recordingStatus = false
367
+ });
368
+ } else {
369
+ this.stopRecording()
370
+ }
371
+ },
372
+ stopRecording() {
373
+ this.recorder.stop() // 停止录音
374
+ this.countdown = 59
375
+ this.vol = 0
376
+ // 获取录音文件
377
+ const pcm = this.recorder.getPCMBlob()
378
+ const file = new File([pcm], 'audio.pcm', {type: 'audio/pcm'})
379
+ let reader = new FileReader();
380
+ reader.readAsDataURL(file)
381
+ reader.onload = async () => {
382
+ this.base64 = reader.result.split('base64,')[1]
383
+ await this.getSpeech()
384
+ }
385
+ },
386
+ getAccessToken() {
387
+ return new Promise((rl, re) => {
388
+ const remember = localStorage.getItem('remember')
389
+ let token = ''
390
+ if(remember === '1') {
391
+ token = localStorage.getItem('sessionId')
392
+ }else {
393
+ token = sessionStorage.getItem('sessionId')
394
+ }
395
+ const xhr = new XMLHttpRequest()
396
+ // xhr.open('POST', 'http://192.168.15.126:8888/zydx/voice/getBaiduToken')
397
+ xhr.open('POST', '/zydx/voice/getBaiduToken')
398
+ xhr.setRequestHeader('Authorization', token)
399
+ const params = new URLSearchParams()
400
+ params.append('type', 'voice')
401
+ xhr.onreadystatechange = () => {
402
+ if (xhr.readyState === 4) {
403
+ if (xhr.status === 200) {
404
+ rl(JSON.parse(xhr.responseText).data)
405
+ }
406
+ }
407
+ }
408
+ xhr.send(params)
409
+ })
410
+ },
411
+ async getSpeech() {
412
+ const _this = this
413
+ const obj = {
414
+ format: "pcm",
415
+ rate: 16000,
416
+ channel: 1,
417
+ cuid: "HpURryNC91ddJmAPq7iwu26OvMDW4jMS",
418
+ speech: this.base64,
419
+ len: this.recorder.fileSize,
420
+ token: await this.getAccessToken()
421
+ };
422
+ _this.voiceLoading = true
423
+ axios.post('/server_api',obj)
424
+ .then(function(data){
425
+ _this.voiceLoading = false
426
+ _this.voiceStatus = false
427
+ _this.recordingStatus = false
428
+ _this.textEditing = true
429
+ _this.voiceContent = ''
430
+ for(let i=0; i< data.data.result.length; i++) {
431
+ if((i + 1) >= data.data.result.length) {
432
+ _this.voiceContent += data.data.result[i]
433
+ }else {
434
+ _this.voiceContent += `${data.data.result[i]}<bt>`
435
+ }
436
+ }
437
+ })
438
+ .catch(function(err){
439
+ console.log(err)
440
+ });
441
+ },
280
442
  enclosureAction(v) {
281
443
  return v.map(x => {
282
444
  x.active = true
@@ -447,7 +609,10 @@ export default {
447
609
  if (v === 'h1') this.editor.chain().focus().setFontSize('18px').setBold().run()
448
610
  if (v === 'h2') this.editor.chain().focus().setFontSize('16px').setBold().run()
449
611
  if (v === 'h3') this.editor.chain().focus().setFontSize('14px').setBold().run()
450
- if (v === 'p') this.editor.chain().focus().setParagraph().setFontSize('14px').unsetBold().run()
612
+ if (v === 'p') {
613
+ this.editor.chain().focus().setFontSize('14px').run()
614
+ this.editor.chain().focus().unsetBold().run()
615
+ }
451
616
  if (v === 'bold') this.editor.chain().focus().toggleBold().run()
452
617
  if (v === 'center' || v === 'left' || v === 'right') this.editor.chain().focus().setTextAlign(v).run()
453
618
  if (v === 'add') {
@@ -465,6 +630,142 @@ export default {
465
630
  </script>
466
631
 
467
632
  <style scoped>
633
+ .text-editing-but{
634
+ text-align: center;
635
+ margin-top: 5px;
636
+ }
637
+ .text-editing{
638
+ position: fixed;
639
+ left: 0;
640
+ right: 0;
641
+ top: 0;
642
+ bottom: 0;
643
+ z-index: 50;
644
+ display: flex;
645
+ align-items: center;
646
+ padding-left: 320px;
647
+ }
648
+ .text-editing-cont{
649
+ width: 600px;
650
+ padding: 20px;
651
+ box-sizing: border-box;
652
+ box-shadow: 0 0 10px rgba(204,204,204,.3);
653
+ background: #fff;
654
+ margin: 0 auto;
655
+ display: inline-block;
656
+ }
657
+ .text-editing-cont p{
658
+ font-size: 16px;
659
+ line-height: 24px;
660
+ font-weight: 700;
661
+ }
662
+ .mic-anim .microphone1{
663
+ animation: mic-anim 1.5s infinite;
664
+ }
665
+ @keyframes mic-anim{
666
+ 0%{
667
+ background: rgba(67, 207, 124, 0.2);
668
+ }
669
+ 80%{
670
+ background: rgba(67, 207, 124, 0.4);
671
+ }
672
+ 100%{
673
+ background: rgba(67, 207, 124, 0.2);
674
+ }
675
+ }
676
+ .mic-anim .microphone2{
677
+ animation: mic-anim2 1.5s infinite;
678
+ }
679
+ @keyframes mic-anim2{
680
+ 0%{
681
+ background: rgba(67, 207, 124, 0.4);
682
+ }
683
+ 40%{
684
+ background: rgba(67, 207, 124, 0.6);
685
+ }
686
+ 80%{
687
+ background: rgba(67, 207, 124, 0.4);
688
+ }
689
+ 100%{
690
+ background: rgba(67, 207, 124, 0.4);
691
+ }
692
+ }
693
+ .mic-anim .microphone3{
694
+ animation: mic-anim3 1.5s infinite;
695
+ }
696
+ @keyframes mic-anim3{
697
+ 0%{
698
+ background: rgba(67, 207, 124, 0.8);
699
+ }
700
+ 20%{
701
+ background: rgba(67, 207, 124, 1);
702
+ }
703
+ 40%{
704
+ background: rgba(67, 207, 124, 0.8);
705
+ }
706
+ 100%{
707
+ background: rgba(67, 207, 124, 0.8);
708
+ }
709
+ }
710
+ .microphone{
711
+ position: fixed;
712
+ left: 50%;
713
+ top: 50%;
714
+ z-index: 50;
715
+ width: 200px;
716
+ margin-left: 60px;
717
+ margin-top: -120px;
718
+ }
719
+ .microphone-cont{
720
+ width: 200px;
721
+ height: 200px;
722
+ border-radius: 50%;
723
+ position: relative;
724
+ }
725
+ .microphone1{
726
+ width: 200px;
727
+ height: 200px;
728
+ border-radius: 50%;
729
+ background: rgba(67, 207, 124, 0.3);
730
+ }
731
+ .microphone2{
732
+ width: 160px;
733
+ height: 160px;
734
+ border-radius: 50%;
735
+ background: rgba(67, 207, 124, 0.5);
736
+ position: absolute;
737
+ top: 50%;
738
+ left: 50%;
739
+ z-index: 1;
740
+ transform: translate(-50%,-50%);
741
+ }
742
+ .microphone3{
743
+ width: 120px;
744
+ height: 120px;
745
+ border-radius: 50%;
746
+ background: rgba(67, 207, 124, 0.8);
747
+ position: absolute;
748
+ top: 50%;
749
+ left: 50%;
750
+ z-index: 1;
751
+ transform: translate(-50%,-50%);
752
+ text-align: center;
753
+ padding-top: 18px;
754
+ box-sizing: border-box;
755
+ cursor: pointer;
756
+ }
757
+ .microphone3 p{
758
+ font-size: 12px;
759
+ color: #fff;
760
+ line-height: 18px;
761
+ }
762
+ .microphone-text{
763
+ text-align: center;
764
+ margin-top: 12px;
765
+ font-size: 18px;
766
+ line-height: 26px;
767
+ font-weight: 700;
768
+ }
468
769
  :deep(.imgCont) {
469
770
  line-height: 0 !important;
470
771
  }
@@ -628,4 +929,18 @@ export default {
628
929
  .but-f {
629
930
  float: left;
630
931
  }
932
+
933
+ .voice {
934
+ display: inline-block;
935
+ position: relative;
936
+ }
937
+ .schedule span {
938
+ font-size: 12px;
939
+ position: absolute;
940
+ top: 0;
941
+ left: 5px;
942
+ z-index: 1;
943
+ transform: scale(.8);
944
+ color: #fff;
945
+ }
631
946
  </style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <div>
3
+ <svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 38 68" width="36" height="68">
4
+ <path id="并集_轮廓_" data-name="并集 (轮廓)" fill="#ccc"
5
+ d="M10,44a3,3,0,0,1-3-3V3a3,3,0,0,1,3-3H28a3,3,0,0,1,3,3V41a3,3,0,0,1-3,3Zm17-4V4H11V40ZM0,47V24a2,2,0,0,1,4,0V45a2,2,0,0,0,2,2H32a2,2,0,0,0,2-2V24a2,2,0,0,1,4,0V47a4,4,0,0,1-4,4H21v9c7.34.26,13,1.93,13,4,0,2.21-6.72,4-15,4S4,66.21,4,64c0-2,5.66-3.7,13-4V51H4A4,4,0,0,1,0,47ZM19,64h.79L19,64l-.79,0Z"/>
6
+ <rect fill="#fff" x="11" y="4" width="16" height="36"/>
7
+ <rect class="volume" :height="volume(vol)" width="12" :y="volume2(vol)" x="13" :fill="vol === 0? '#CCCCCC':'#43cf7c'"/>
8
+ </svg>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ export default {
14
+ name: "microphone",
15
+ props: {
16
+ vol: {
17
+ type: Number,
18
+ default: 0
19
+ }
20
+ },
21
+ data() {
22
+ return {}
23
+ },
24
+ methods: {
25
+ volume(v) {
26
+ if(v === 0) {
27
+ return 32
28
+ }else {
29
+ return v/3 > 32 ? 32 : v/5
30
+ }
31
+ },
32
+ volume2(v) {
33
+ if(v === 0) {
34
+ return 6
35
+ }else {
36
+ return 6 + 32 - this.volume(v)
37
+ }
38
+ }
39
+ }
40
+ }
41
+ </script>
42
+
43
+ <style scoped>
44
+ .volume {
45
+ transition: all 0.2s;
46
+ }
47
+ </style>
package/src/index.js CHANGED
@@ -79,7 +79,7 @@ function install(app) {
79
79
  }
80
80
 
81
81
  export default {
82
- version: '1.32.254',
82
+ version: '1.32.255',
83
83
  install,
84
84
  Calendar,
85
85
  Message,