zydx-plus 1.32.254 → 1.32.256

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.256",
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
+ })
330
+ this.recorder.onprogress = function (params) {
331
+ if(_this.countdown <= 0) {
332
+ _this.stopRecording()
333
+ }else {
334
+ _this.countdown = 59 - parseInt(params.duration)
335
+ _this.fileSize = params.fileSize
336
+ _this.vol = params.vol
337
+ }
338
+ }
278
339
  },
279
340
  methods: {
341
+ editingConfirm() {
342
+ this.textEditing = false
343
+ const html = this.$refs.textarea.getContent().split('<br>')
344
+ let editorHtml = this.editor.getHTML()
345
+ for(let i=0; i< html.length; i++) {
346
+ editorHtml += `<p>${html[i]}</p>`
347
+ }
348
+ this.editor.commands.setContent(editorHtml.replace(/<p><\/p>/g, ''))
349
+ },
350
+ editingCancel() {
351
+ this.textEditing = false
352
+ },
353
+ // 语音输入
354
+ voice() {
355
+ this.voiceStatus = !this.voiceStatus
356
+ this.recorder.stop() // 停止录音
357
+ this.recorder.destroy() // 销毁录音
358
+ },
359
+ startVoice() {
360
+ if (!this.recordingStatus) {
361
+ this.recorder.start().then(() => { // 开始录音
362
+ this.fileSize = 0
363
+ this.recordingStatus = true
364
+ }, (error) => {
365
+ this.recordingStatus = false
366
+ });
367
+ } else {
368
+ this.stopRecording()
369
+ }
370
+ },
371
+ stopRecording() {
372
+ this.recorder.stop() // 停止录音
373
+ this.countdown = 59
374
+ this.vol = 0
375
+ // 获取录音文件
376
+ const pcm = this.recorder.getPCMBlob()
377
+ const file = new File([pcm], 'audio.pcm', {type: 'audio/pcm'})
378
+ let reader = new FileReader();
379
+ reader.readAsDataURL(file)
380
+ reader.onload = async () => {
381
+ this.base64 = reader.result.split('base64,')[1]
382
+ await this.getSpeech()
383
+ }
384
+ },
385
+ getAccessToken() {
386
+ return new Promise((rl, re) => {
387
+ const remember = localStorage.getItem('remember')
388
+ let token = ''
389
+ if(remember === '1') {
390
+ token = localStorage.getItem('sessionId')
391
+ }else {
392
+ token = sessionStorage.getItem('sessionId')
393
+ }
394
+ const xhr = new XMLHttpRequest()
395
+ // xhr.open('POST', 'http://192.168.15.126:8888/zydx/voice/getBaiduToken')
396
+ xhr.open('POST', '/zydx/voice/getBaiduToken')
397
+ // xhr.setRequestHeader('Authorization', '5c9826f8-da53-44f1-9141-5917df6acab2')
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>
@@ -35,7 +35,7 @@
35
35
  </div>
36
36
  <div class="tip-img" v-if="type === 'input'">
37
37
  <div class="tip-input" v-for="(item,index) in inputArr" :key="index">
38
- <span v-if="item.name"><em v-html="item.name"></em><i v-if="item.required">*</i></span>
38
+ <span v-if="item.name"><em>{{ item.name }}</em><i v-if="item.required">*</i></span>
39
39
  <div v-if="item.type === 'file'" class="file-cont">
40
40
  <em>{{ fileName }}</em>
41
41
  <label>
@@ -54,8 +54,8 @@
54
54
  v-model="item.value" :disabled="item.disabled"/>
55
55
  <b>{{ item.tail }}</b>
56
56
  </div>
57
- <div style="display: inline-block;">
58
- <Select v-if="item.type === 'select'" :options="item.option"
57
+ <div v-if="item.type === 'select'" style="display: inline-block;width: 300px;">
58
+ <Select :options="item.option"
59
59
  v-model:value="item.selectValue"></Select>
60
60
  </div>
61
61
  <div class="cal" v-if="item.type === 'calender'">
@@ -28,8 +28,8 @@
28
28
  cursor: pointer;
29
29
  }
30
30
  .tip-box {
31
- width: 480px;
32
- padding: 40px 40px;
31
+ width: 600px;
32
+ padding: 60px 100px 40px 100px;
33
33
  background-color: white;
34
34
  border-radius: 5px;
35
35
  border: 5px rgba(0, 0, 0, .1) solid;
@@ -140,6 +140,9 @@
140
140
 
141
141
  .tip-input > span > em {
142
142
  font-style: normal;
143
+ min-width: 65px;
144
+ display: inline-block;
145
+ text-align-last: justify;
143
146
  }
144
147
 
145
148
  .tip-input > span > i {
@@ -153,7 +156,7 @@
153
156
  }
154
157
 
155
158
  .tip-input input {
156
- width: 211px;
159
+ width: 300px;
157
160
  height: 32px;
158
161
  box-sizing: border-box;
159
162
  font-size: 16px;
@@ -165,7 +168,7 @@
165
168
  }
166
169
 
167
170
  .tip-input > select {
168
- width: 210px;
171
+ width: 300px;
169
172
  height: 30px;
170
173
  box-sizing: border-box;
171
174
  font-size: 16px;
@@ -229,7 +232,7 @@
229
232
  }
230
233
 
231
234
  .number-input {
232
- width: 211px;
235
+ width: 300px;
233
236
  height: 32px;
234
237
  box-sizing: border-box;
235
238
  font-size: 16px;
@@ -244,7 +247,7 @@
244
247
  border: 0 !important;
245
248
  box-shadow: none !important;
246
249
  height: 30px !important;
247
- width: 240px !important;
250
+ width: 320px !important;
248
251
  }
249
252
 
250
253
  .file-cont {
@@ -267,7 +270,7 @@
267
270
  .file-cont > em {
268
271
  display: inline-block;
269
272
  font-style: normal;
270
- width: 211px;
273
+ width: 300px;
271
274
  height: 32px;
272
275
  box-sizing: border-box;
273
276
  font-size: 16px;
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.256',
83
83
  install,
84
84
  Calendar,
85
85
  Message,