zydx-plus 1.33.334 → 1.33.336

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.33.334",
3
+ "version": "1.33.336",
4
4
  "description": "Vue.js",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -25,7 +25,6 @@
25
25
  "snabbdom": "^3.5.1",
26
26
  "katex": "^0.15.6",
27
27
  "simple-mind-map": "^0.9.6",
28
- "html2json": "^1.0.2",
29
28
  "@tiptap/starter-kit": "^2.0.3",
30
29
  "@tiptap/vue-3": "^2.0.3",
31
30
  "@tiptap/extension-bubble-menu": "^2.1.0",
@@ -65,6 +65,12 @@ export function butJson (editor,data) {
65
65
  menuKeys: [],
66
66
  html: `<p style="text-align: center;"><span style="color: rgb(225, 60, 57);font-size: 48px;">XXXXXXX(单位)文件</span></p><p data-signId="red" style="text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 16px;">xxx〔xx〕xxxx 号</span></p>`
67
67
  },
68
+ // voiceInput: {
69
+ // name: '语音输入',
70
+ // flip:'关闭语音',
71
+ // key: 'voiceInput',
72
+ // menuKeys: []
73
+ // },
68
74
  authorMenu: {
69
75
  name: '作者',
70
76
  key: 'authorMenu',
@@ -10,7 +10,8 @@
10
10
  </label>
11
11
  </div>
12
12
  <div v-else class="editor-but-name" @click="butTap(item,0)">
13
- <span v-html="item.name"></span>
13
+ <span v-if="item.key === 'voiceInput'" :class="{'but-name-color':voiceOpen}" v-html="voiceOpen?item.flip:item.name"></span>
14
+ <span v-else v-html="item.name"></span>
14
15
  <img v-if="item.menuKeys.length > 0"
15
16
  src="data:image/png;base64,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"
16
17
  alt=""/>
@@ -28,6 +29,11 @@
28
29
  </ul>
29
30
  </div>
30
31
  </div>
32
+ <div class="editor-but" >
33
+ <div class="editor-but-name" @click="butTap({key:'voiceInput'},0)">
34
+ <span :class="{'but-name-color':voiceOpen}" v-html="voiceOpen?'关闭语音':'语音输入'"></span>
35
+ </div>
36
+ </div>
31
37
  <!-- <div class="editor-but">-->
32
38
  <!-- <div class="editor-but-name">-->
33
39
  <!-- <label>-->
@@ -37,7 +43,7 @@
37
43
  <!-- </div>-->
38
44
  <!-- </div>-->
39
45
  </div>
40
- <div class="editor-content" :class="{'editor-content-show': !editableShow}">
46
+ <div class="editor-content" :class="{'editor-content-show': !editableShow }">
41
47
  <div class="editing">
42
48
  <div class="editing-header" v-if="signMenuShow">
43
49
  <img :src="menusData('signMenu')?.ico" alt=""/>
@@ -64,8 +70,8 @@
64
70
  <img :src="menusData('signMenu')?.ico" alt=""/>
65
71
  <span>{{ menusData('signMenu')?.text }}</span>
66
72
  </div>
67
- <div class="read-only-page" @click="menusTap" :style="{height: wit * 1.4 + 'px',width: wit + 'px'}"
68
- v-for="(item,index) in htmlArr">
73
+ <div class="read-only-page" @click="menusTap" :style="{height: wit * 1.6 + 'px',width: wit + 'px'}"
74
+ v-for="(item,index) in htmlArr" :key="index">
69
75
  <div class="read-only-p" v-html="item"></div>
70
76
  <div class="read-only-a">{{ index + 1 }}/{{ htmlArr.length }}</div>
71
77
  </div>
@@ -79,13 +85,24 @@
79
85
  </div>
80
86
  </div>
81
87
  <div class="down-html" id="test" v-html="htmlArr2"></div>
88
+ <div v-if="voiceOpen" class="speak"
89
+ @mousedown.stop="mousedown"
90
+ @mouseup.stop="mouseup"
91
+ :style="{transform: `translate(${x}px, ${y}px)`}">
92
+ <div class="speak-cont">
93
+ <svg t="1698630789078" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4553" width="15" height="15"><path d="M533.84533333 930.88426667c-13.65333333 0-24.576-10.92266667-24.576-24.576v-122.33386667c0-13.65333333 10.92266667-24.576 24.576-24.576s24.576 10.92266667 24.576 24.576v122.33386667c-0.54613333 13.65333333-11.4688 24.576-24.576 24.576zM533.84533333 686.21653333c-101.03466667 0-183.5008-82.46613333-183.5008-183.5008V258.048c0-101.03466667 82.46613333-183.5008 183.5008-183.5008s183.5008 82.46613333 183.5008 183.5008v244.66773333c0 101.03466667-82.46613333 183.5008-183.5008 183.5008z m0-563.06346666c-74.27413333 0-134.89493333 60.6208-134.89493333 134.89493333v244.66773333c0 74.27413333 60.6208 134.89493333 134.89493333 134.89493334s134.89493333-60.6208 134.89493334-134.89493334V258.048c-0.54613333-74.27413333-60.6208-134.89493333-134.89493334-134.89493333z" fill="#fff" p-id="4554"></path><path d="M533.84533333 808.5504c-168.7552 0-305.83466667-137.07946667-305.83466666-305.83466667 0-13.65333333 10.92266667-24.576 24.576-24.576s24.576 10.92266667 24.576 24.576c0 141.99466667 115.23413333 257.2288 257.2288 257.2288S790.528 644.7104 790.528 502.71573333c0-13.65333333 10.92266667-24.576 24.576-24.576s24.576 10.92266667 24.576 24.576c0 168.7552-137.07946667 305.83466667-305.83466667 305.83466667zM729.36106667 955.46026667H337.78346667c-13.65333333 0-24.576-10.92266667-24.576-24.576s10.92266667-24.576 24.576-24.576h391.5776c13.65333333 0 24.576 10.92266667 24.576 24.576s-10.92266667 24.576-24.576 24.576z" fill="#FFF" p-id="4555"></path></svg>
94
+ <svgs :vol="vol"></svgs>
95
+ <span>{{ error? '连接中...' : '正在说话...' }}</span>
96
+ <svg style="cursor: pointer" @click="close" t="1698630749910" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4415" width="20" height="20"><path d="M726.976 274.432a16 16 0 0 0-22.656 0L512 466.752l-192.32-192.32a16 16 0 0 0-22.624 0l-22.656 22.624a16 16 0 0 0 0 22.624l192.32 192.32-192.32 192.32a16 16 0 0 0 0 22.656l22.656 22.624a16 16 0 0 0 22.624 0l192.32-192.32 192.32 192.32a16 16 0 0 0 22.656 0l22.624-22.624a16 16 0 0 0 0-22.624L557.28 512l192.32-192.352a16 16 0 0 0 0-22.624l-22.624-22.624z" fill="#fff" p-id="4416"></path></svg>
97
+ </div>
98
+ </div>
82
99
  </div>
83
100
  </template>
84
101
 
85
102
  <script>
86
103
  import exportWord from 'js-export-word'
87
104
  import mammoth from './mammoth.browser.min'
88
- import {html2json, json2html} from 'html2json'
105
+ import {html2json, json2html} from '@/components/utils/html2json.js'
89
106
  import {butJson} from './butJson'
90
107
  import {Editor, EditorContent} from '@tiptap/vue-3'
91
108
  import StarterKit from '@tiptap/starter-kit'
@@ -105,12 +122,18 @@ import {Contenteditable} from "./extend/contenteditable";
105
122
  import {titleId} from "./extend/title-id";
106
123
  import {dataUrl} from "./extend/data-url";
107
124
  import Mess from '../../tipBox/index'
125
+ import svgs from "@/components/editor2/src/level.vue";
126
+ import Recorder from 'js-audio-recorder'
108
127
 
109
128
  export default {
110
129
  name: 'zydx-editor',
111
- components: {EditorContent},
130
+ components: {svgs, EditorContent},
112
131
  beforeUnmount() {
113
132
  this.editor.destroy()
133
+ this.recorder?.destroy()
134
+ this.ws?.send(JSON.stringify({"type":"CANCEL"}))
135
+ this.ws?.close()
136
+ this.ws = null
114
137
  },
115
138
  data() {
116
139
  return {
@@ -132,7 +155,23 @@ export default {
132
155
  top: '0px',
133
156
  left: '0px'
134
157
  },
135
- menuStast: null
158
+ menuStast: null,
159
+
160
+ voiceOpen:false,
161
+ limits:false,
162
+ speech: {},
163
+ recorder: null,
164
+ ws: null,
165
+ left: 0,
166
+ top: 0,
167
+ isMove: false,
168
+ x: 1600,
169
+ y: 230,
170
+ vol: 0,
171
+ error: false,
172
+ appData: {},
173
+ audioData: [],
174
+ time: {}
136
175
  }
137
176
  },
138
177
  props: {
@@ -202,19 +241,27 @@ export default {
202
241
  deep: true
203
242
  },
204
243
  readOnly: {
205
- handler: function (e, oldVal) {
206
- this.editor.setOptions({
207
- editable: !e
208
- })
209
- if (this.page) {
210
- this.editableShow = !e
211
- this.readOnlyPage() // 只读分页
212
- }
244
+ handler: function (e) {
245
+ let time = setInterval(() => {
246
+ if (this.editor) { // 没有时间以后 停止定时器
247
+ this.editor.setOptions({
248
+ editable: !e
249
+ })
250
+ if (this.page) {
251
+ this.editableShow = !e
252
+ setTimeout(() => {
253
+ this.readOnlyPage() // 只读分页
254
+ },300)
255
+ }
256
+ clearInterval(time) //停止计时器,清除定时器
257
+ }
258
+ }, 10)
213
259
  },
214
- deep: true
260
+ deep: true,
261
+ immediate: true
215
262
  },
216
263
  menusText: {
217
- handler: function (e, oldVal) {
264
+ handler: function () {
218
265
  this.organizeButton()
219
266
  },
220
267
  deep: true
@@ -283,20 +330,27 @@ export default {
283
330
  ],
284
331
  injectCSS: true,
285
332
  onBlur: () => {
333
+ _this.limits = false
286
334
  _this.menuStast = null
335
+ _this.close()
287
336
  _this.butDataName('outlineMenu','大纲级别')
288
337
  _this.butDataName('textMenu','字号')
289
338
  _this.butDataName('titleMenu','字体')
290
339
  },
340
+ // 获取焦点
341
+ onFocus: () => {
342
+ this.limits = true
343
+ },
291
344
  onTransaction: () => {
292
345
  const index = _this.editor.state.selection.$anchor.path[1]
346
+ // console.log(index)
293
347
  const json = _this.editor.getJSON()
294
348
  for (let i = 0; i < json.content.length; i++) {
295
349
  if(index === i) {
296
350
  if(json.content[i].content === undefined) break
297
351
  const attrs = json.content[i].attrs
298
352
  if(attrs.titleId === 'text') {
299
- _this.butDataName('正文文本')
353
+ _this.butDataName('outlineMenu','正文文本')
300
354
  }
301
355
  if(attrs.signId !== null) {
302
356
  _this.butData.map(x => {
@@ -308,6 +362,8 @@ export default {
308
362
  if(attrs.signId === 'title-4') x.name = '四级标题'
309
363
  }
310
364
  })
365
+ }else {
366
+ _this.butDataName('outlineMenu','大纲级别')
311
367
  }
312
368
  if(json.content[i].content[0].marks === undefined) break
313
369
  const style = json.content[i].content[0].marks
@@ -344,6 +400,17 @@ export default {
344
400
  }
345
401
  })
346
402
  _this.organizeButton()
403
+ this.recorderInit()
404
+ document.addEventListener('mousemove', (event) => {
405
+ if (!this.isMove) return
406
+ this.limits = true
407
+ this.x = event.clientX - this.left;
408
+ this.y = event.clientY - this.top;
409
+ })
410
+ // document.addEventListener('click', () => {
411
+ // // if(this.limits) return
412
+ // // this.close()
413
+ // })
347
414
  },
348
415
  emits: ['confirm', 'enclosure', 'enlDownload', 'enlSee'],
349
416
  methods: {
@@ -515,7 +582,7 @@ export default {
515
582
  const data = document.querySelectorAll('.editing-cont')[0].childNodes[0].childNodes
516
583
  this.wit = document.getElementsByClassName('editor-content')[0].offsetWidth + 20
517
584
  if (this.wit > 900) this.wit = 900
518
- let max = this.wit * 1.4 - 200
585
+ let max = this.wit * 1.6 - 246
519
586
  let pHeight = 0
520
587
  let html = ''
521
588
  for (let i = 0; i < data.length; i++) {
@@ -533,19 +600,19 @@ export default {
533
600
  html = ''
534
601
  }
535
602
  }
536
- let text = data[i].offsetHeight
537
603
  if (data[i].dataset?.signid === 'ack') {
538
604
  this.htmlArr.push(html)
539
605
  pHeight = 0
540
606
  html = ''
541
607
  }
608
+ let text = data[i].offsetHeight
542
609
  if ((pHeight + text) > max) {
543
610
  const {start, end, size} = this.rows(data[i], max - pHeight)
544
- html += `<p class="text"><span style="font-family: SimSun; font-size: ${size}px">${start.data}</span></p>`
611
+ html += `<p class="text"><span style="font-family: Microsoft Yahei; font-size: ${size}px">${start.data}</span></p>`
545
612
  this.htmlArr.push(html)
546
613
  pHeight = 0
547
614
  html = ''
548
- html += `<p class="text"><span style="font-family: SimSun;font-size: ${size}px">${end.data}</span></p>`
615
+ html += `<p class="text"><span style="font-family: Microsoft Yahei;font-size: ${size}px">${end.data}</span></p>`
549
616
  pHeight = end.size
550
617
  } else {
551
618
  pHeight += text
@@ -621,7 +688,7 @@ export default {
621
688
  width += 3.25;
622
689
  num += 1
623
690
  } else if (/[\u4e00-\u9fa5]/.test(text[i])) { //中文匹配
624
- width += 10.105;
691
+ width += 10.102;
625
692
  num += 1
626
693
  } else if (/\(|\)/.test(text[i])) { // 括号匹配
627
694
  width += 3.73;
@@ -835,6 +902,48 @@ export default {
835
902
  }
836
903
  })
837
904
  },
905
+ cursorPosition(data, index) {
906
+ let num = 0
907
+ for (let i = 0; i < data.length; i++) {
908
+ num += data[i].nodeSize
909
+ if (i === index) break
910
+ }
911
+ return num
912
+ },
913
+ selectionPath(v, n) {
914
+ let num = 0
915
+ const path = this.editor.state.selection.$head.path[0].content.content
916
+ for (let i = 0; i < path.length; i++) {
917
+ num += path[i].nodeSize
918
+ if (n !== undefined) {
919
+ if (i === n) break
920
+ } else {
921
+ if (path[i].attrs?.signId === v) {
922
+ if (v === 'red') num += 1
923
+ break
924
+ }
925
+ }
926
+ }
927
+ return num
928
+ },
929
+ signIdData(id) {
930
+ return this.$nextTick(() => {
931
+ let state = -1
932
+ const json = this.editor.getJSON()
933
+ for (let i = 0; i < json.content.length; i++) {
934
+ if (json.content[i].attrs?.signId === id) {
935
+ state = i
936
+ break
937
+ }
938
+ }
939
+ return state
940
+ })
941
+ },
942
+ selection() {
943
+ const {from} = this.editor.state.selection
944
+ return from
945
+ },
946
+
838
947
  async butTap(data, key) {
839
948
  if(data.key === 'textMenu' && key === 0 || data.key === 'titleMenu' && key === 0) return
840
949
  // 标志
@@ -981,51 +1090,198 @@ export default {
981
1090
  this.imgPop = true
982
1091
  }
983
1092
  }
1093
+ if (data.key === 'voiceInput' ){
1094
+ this.voice()
1095
+ }
984
1096
  setTimeout(() => {
985
1097
  this.menuStast = null
986
1098
  },1000)
987
1099
  },
988
- cursorPosition(data, index) {
989
- let num = 0
990
- for (let i = 0; i < data.length; i++) {
991
- num += data[i].nodeSize
992
- if (i === index) break
1100
+ close() {
1101
+ if(this.ws === null) return
1102
+ this.voiceOpen = false
1103
+ this.ws?.send(JSON.stringify({"type":"CANCEL"}))
1104
+ this.ws?.close()
1105
+ this.ws = null
1106
+ this.recorder.stop() // 停止录音
1107
+ this.recorder.destroy()
1108
+ },
1109
+ voice() {
1110
+ this.voiceOpen = !this.voiceOpen
1111
+ this.limits = false
1112
+ if(this.voiceOpen) {
1113
+ this.recorder.start().then(() => { // 开始录音
1114
+ this.audioData = []
1115
+ this.appID()
1116
+ }, (err) => {
1117
+ Mess({
1118
+ type: 'text',
1119
+ cancelShow: false,
1120
+ promptContent: '录音失败,请检查麦克风是否可用'
1121
+ })
1122
+ });
1123
+ }else {
1124
+ this.close()
993
1125
  }
994
- return num
995
1126
  },
996
- selectionPath(v, n) {
997
- let num = 0
998
- const path = this.editor.state.selection.$head.path[0].content.content
999
- for (let i = 0; i < path.length; i++) {
1000
- num += path[i].nodeSize
1001
- if (n !== undefined) {
1002
- if (i === n) break
1003
- } else {
1004
- if (path[i].attrs?.signId === v) {
1005
- if (v === 'red') num += 1
1006
- break
1127
+ appID() {
1128
+ let token = null
1129
+ let remember = localStorage.getItem('remember')
1130
+ if(remember === '1') {
1131
+ token = localStorage.getItem('sessionId')
1132
+ }else {
1133
+ token = sessionStorage.getItem('sessionId')
1134
+ }
1135
+ const xhr = new XMLHttpRequest()
1136
+ // xhr.open('GET', 'http://192.168.15.124:8888/zydx/voice/getDesKeyId')
1137
+ // xhr.setRequestHeader('Authorization', '4a7ab02c-11b7-420f-bf85-ac5549b2aa81')
1138
+ xhr.open('GET', '/zydx/voice/getDesKeyId')
1139
+ xhr.setRequestHeader('Authorization', token)
1140
+ this.error = true
1141
+ xhr.onreadystatechange = () => {
1142
+ if (xhr.readyState === 4) {
1143
+ if (xhr.status === 200) {
1144
+ this.appData = JSON.parse(xhr.responseText).data
1145
+ this.webSocketInit()
1007
1146
  }
1008
1147
  }
1009
1148
  }
1010
- return num
1149
+ xhr.send()
1011
1150
  },
1012
- signIdData(id) {
1013
- return this.$nextTick(() => {
1014
- let state = -1
1015
- const json = this.editor.getJSON()
1016
- for (let i = 0; i < json.content.length; i++) {
1017
- if (json.content[i].attrs?.signId === id) {
1018
- state = i
1019
- break
1151
+ // 初始化音频获取
1152
+ recorderInit(){
1153
+ let _this = this
1154
+ // 初始化录音
1155
+ this.recorder = new Recorder({
1156
+ sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
1157
+ sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
1158
+ numChannels: 1, // 声道,支持 1 或 2, 默认是1
1159
+ })
1160
+ this.recorder.onprogress = function (params) {
1161
+ _this.vol = params.vol
1162
+ }
1163
+ },
1164
+ webSocketInit() {
1165
+ const _this = this
1166
+ this.ws = new WebSocket(`wss://vop.baidu.com/realtime_asr?sn=${this.getRandomCode(15)}`)
1167
+ this.ws.binaryType = 'arraybuffer'
1168
+ this.ws.onopen = function () {
1169
+ _this.error = false
1170
+ const json = {
1171
+ type: 'START',
1172
+ data: {
1173
+ appid: Number(_this.appData.qfClientId),
1174
+ appkey: _this.appData.qfClientSecret,
1175
+ dev_pid: 15372,
1176
+ cuid: 'HpURryNC91ddJmAPq7iwu26OvMDW4jMS',
1177
+ format: 'pcm',
1178
+ sample: 16000,
1020
1179
  }
1021
1180
  }
1022
- return state
1023
- })
1181
+ _this.ws.send(JSON.stringify(json))
1182
+ _this.getAudioSuccess()
1183
+ }
1184
+ this.ws.onmessage = function (e) {
1185
+ const data = JSON.parse(e.data)
1186
+ if(data.err_no === 0){
1187
+ const json = _this.editor.getJSON()
1188
+ const index = _this.editor.state.selection.$anchor.path[1]
1189
+ if(data.start_time === _this.time.start_time) {
1190
+ const text = json.content[index].content[0].text
1191
+ json.content[index].content[0].text = text.slice(0, text.length - _this.time.result.length) + data.result
1192
+ _this.editor.commands.setContent(json)
1193
+ }else {
1194
+ _this.editor.chain().focus().insertContentAt(_this.selection(), data.result).run()
1195
+ }
1196
+ _this.time = data
1197
+ }
1198
+ }
1199
+ this.ws.onerror = function () {
1200
+ // 连接失败重连
1201
+ setTimeout(() => {
1202
+ _this.webSocketInit()
1203
+ }, 5000)
1204
+ }
1024
1205
  },
1025
- selection() {
1026
- const {from} = this.editor.state.selection
1027
- return from
1206
+ getAudioSuccess() {
1207
+ let that = this
1208
+ const mediaStreamSource = that.recorder.audioInput
1209
+ // 创建一个音频分析对象,采样的缓冲区大小为0(自动适配),输入和输出都是单声道
1210
+ const scriptProcessor = that.recorder.context.createScriptProcessor(1024, 1, 1);
1211
+ scriptProcessor.onaudioprocess = (e) => {
1212
+ // 去处理音频数据
1213
+ const inputData = e.inputBuffer.getChannelData(0)
1214
+ const output = that.to16kHz(inputData, that.recorder.context.sampleRate);
1215
+ const audioData = that.to16BitPCM(output);
1216
+ that.audioData.push(...new Int8Array(audioData.buffer));
1217
+ if (that.audioData.length > 10240) {
1218
+ const audioDataArray = new Int8Array(that.audioData);
1219
+ that.ws.send(audioDataArray)
1220
+ that.audioData = [];
1221
+ }
1222
+ }
1223
+ mediaStreamSource.connect(scriptProcessor);
1224
+ scriptProcessor.connect(that.recorder.context.destination);
1225
+ },
1226
+ speechDown(e) {
1227
+ this.speech = {
1228
+ x: e.clientX - e.offsetX,
1229
+ y: e.clientY - e.offsetY,
1230
+ }
1231
+ },
1232
+ mousedown(event) {
1233
+ event.preventDefault()
1234
+ //鼠标按下事件
1235
+ this.left = event.offsetX;
1236
+ this.top = event.offsetY;
1237
+ this.isMove = true
1238
+ },
1239
+ mouseup() {
1240
+ this.isMove = false
1241
+ setTimeout(() => {
1242
+ this.limits = false
1243
+ },10)
1244
+ },
1245
+ to16kHz(audioData, sampleRate = 44100) {
1246
+ const data = new Float32Array(audioData);
1247
+ const fitCount = Math.round(data.length * (16000 / sampleRate));
1248
+ const newData = new Float32Array(fitCount);
1249
+ const springFactor = (data.length - 1) / (fitCount - 1);
1250
+ newData[0] = data[0];
1251
+ for (let i = 1; i < fitCount - 1; i++) {
1252
+ const tmp = i * springFactor;
1253
+ const before = Math.floor(tmp).toFixed();
1254
+ const after = Math.ceil(tmp).toFixed();
1255
+ const atPoint = tmp - before;
1256
+ newData[i] = data[before] + (data[after] - data[before]) * atPoint;
1257
+ }
1258
+ newData[fitCount - 1] = data[data.length - 1];
1259
+ return newData;
1260
+ },
1261
+ to16BitPCM(input) {
1262
+ const dataLength = input.length * (16 / 8);
1263
+ const dataBuffer = new ArrayBuffer(dataLength);
1264
+ const dataView = new DataView(dataBuffer);
1265
+ let offset = 0;
1266
+ for (let i = 0; i < input.length; i++, offset += 2) {
1267
+ const s = Math.max(-1, Math.min(1, input[i]));
1268
+ dataView.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
1269
+ }
1270
+ return dataView;
1028
1271
  },
1272
+ getRandomCode(length) {
1273
+ if (length > 0) {
1274
+ let data = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
1275
+ let nums = "";
1276
+ for (let i = 0; i < length; i++) {
1277
+ let r = parseInt(Math.random() * 61);
1278
+ nums += data[r];
1279
+ }
1280
+ return nums.replace(/(.{4})/g, "$1-");
1281
+ } else {
1282
+ return false;
1283
+ }
1284
+ }
1029
1285
  }
1030
1286
  }
1031
1287
  </script>
@@ -1068,7 +1324,7 @@ export default {
1068
1324
 
1069
1325
  .read-only-page {
1070
1326
  width: 100%;
1071
- padding: 120px 100px 66px 100px;
1327
+ padding: 120px 0 66px 0;
1072
1328
  background-color: #fff;
1073
1329
  box-sizing: border-box;
1074
1330
  position: relative;
@@ -1324,6 +1580,7 @@ li {
1324
1580
  top: -9999px;
1325
1581
  left: 0;
1326
1582
  z-index: -1;
1583
+ width: 620px;
1327
1584
  }
1328
1585
 
1329
1586
  .editing {
@@ -1356,4 +1613,31 @@ li {
1356
1613
  position: absolute;
1357
1614
  z-index: 10;
1358
1615
  }
1616
+ .but-name-color{
1617
+ color: #00ff00;
1618
+ }
1619
+ .speak{
1620
+ position: fixed;
1621
+ top: 0;
1622
+ left: 0;
1623
+ z-index: 50;
1624
+ cursor: move;
1625
+ }
1626
+ .speak-cont{
1627
+ background: rgba(67, 207, 124, 1);
1628
+ color: #fff;
1629
+ padding: 0 10px;
1630
+ height: 30px;
1631
+ line-height: 30px;
1632
+ display: inline-block;
1633
+ border-radius: 20px;
1634
+ }
1635
+ .speak-cont svg{
1636
+ vertical-align: middle;
1637
+ margin-top: -3px;
1638
+ }
1639
+ .speak-cont span{
1640
+ font-size: 14px;
1641
+ padding: 0 5px;
1642
+ }
1359
1643
  </style>
@@ -99,7 +99,7 @@
99
99
  </template>
100
100
  <script>
101
101
  import Recorder from 'js-audio-recorder'
102
- import {html2json, json2html} from 'html2json'
102
+ import {html2json, json2html} from '@/components/utils/html2json.js'
103
103
  import {Editor, EditorContent} from '@tiptap/vue-3'
104
104
  import StarterKit from '@tiptap/starter-kit'
105
105
  import Image from '@tiptap/extension-image'
@@ -45,7 +45,7 @@
45
45
  </template>
46
46
 
47
47
  <script>
48
- import {html2json, json2html} from 'html2json'
48
+ import {html2json, json2html} from '@/components/utils/html2json.js'
49
49
  import svgs from './icon.vue'
50
50
 
51
51
  export default {
@@ -61,7 +61,7 @@
61
61
  </template>
62
62
 
63
63
  <script>
64
- import {html2json, json2html} from 'html2json'
64
+ import {html2json, json2html} from '@/components/utils/html2json.js'
65
65
  import zydxTextarea from "../../textarea/src/textarea"
66
66
  import Range from "./range";
67
67
 
@@ -0,0 +1,466 @@
1
+ var DEBUG = false;
2
+ var debug = DEBUG ? console.log.bind(console) : function() {};
3
+
4
+ // Regular Expressions for parsing tags and attributes
5
+ var startTag =
6
+ /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
7
+ endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/,
8
+ attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
9
+
10
+ // Empty Elements - HTML 5
11
+ var empty = makeMap(
12
+ "area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
13
+
14
+ // Block Elements - HTML 5
15
+ var block = makeMap(
16
+ "a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video"
17
+ );
18
+
19
+ // Inline Elements - HTML 5
20
+ var inline = makeMap(
21
+ "abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var"
22
+ );
23
+
24
+ // Elements that you can, intentionally, leave open
25
+ // (and which close themselves)
26
+ var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
27
+
28
+ // Attributes that have their values filled in disabled="disabled"
29
+ var fillAttrs = makeMap(
30
+ "checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
31
+
32
+ // Special Elements (can contain anything)
33
+ var special = makeMap("script,style");
34
+
35
+ var HTMLParser = function(html, handler) {
36
+ var index, chars, match, stack = [],
37
+ last = html;
38
+ stack.last = function() {
39
+ return this[this.length - 1];
40
+ };
41
+
42
+ while (html) {
43
+ chars = true;
44
+
45
+ // Make sure we're not in a script or style element
46
+ if (!stack.last() || !special[stack.last()]) {
47
+
48
+ // Comment
49
+ if (html.indexOf("<!--") == 0) {
50
+ index = html.indexOf("-->");
51
+
52
+ if (index >= 0) {
53
+ if (handler.comment)
54
+ handler.comment(html.substring(4, index));
55
+ html = html.substring(index + 3);
56
+ chars = false;
57
+ }
58
+
59
+ // end tag
60
+ } else if (html.indexOf("</") == 0) {
61
+ match = html.match(endTag);
62
+
63
+ if (match) {
64
+ html = html.substring(match[0].length);
65
+ match[0].replace(endTag, parseEndTag);
66
+ chars = false;
67
+ }
68
+
69
+ // start tag
70
+ } else if (html.indexOf("<") == 0) {
71
+ match = html.match(startTag);
72
+
73
+ if (match) {
74
+ html = html.substring(match[0].length);
75
+ match[0].replace(startTag, parseStartTag);
76
+ chars = false;
77
+ }
78
+ }
79
+
80
+ if (chars) {
81
+ index = html.indexOf("<");
82
+
83
+ var text = index < 0 ? html : html.substring(0, index);
84
+ html = index < 0 ? "" : html.substring(index);
85
+
86
+ if (handler.chars)
87
+ handler.chars(text);
88
+ }
89
+
90
+ } else {
91
+ html = html.replace(new RegExp("([\\s\\S]*?)<\/" + stack.last() + "[^>]*>"), function(all, text) {
92
+ text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, "$1$2");
93
+ if (handler.chars)
94
+ handler.chars(text);
95
+
96
+ return "";
97
+ });
98
+
99
+ parseEndTag("", stack.last());
100
+ }
101
+
102
+ if (html == last)
103
+ throw "Parse Error: " + html;
104
+ last = html;
105
+ }
106
+
107
+ // Clean up any remaining tags
108
+ parseEndTag();
109
+
110
+ function parseStartTag(tag, tagName, rest, unary) {
111
+ tagName = tagName.toLowerCase();
112
+
113
+ if (block[tagName]) {
114
+ while (stack.last() && inline[stack.last()]) {
115
+ parseEndTag("", stack.last());
116
+ }
117
+ }
118
+
119
+ if (closeSelf[tagName] && stack.last() == tagName) {
120
+ parseEndTag("", tagName);
121
+ }
122
+
123
+ unary = empty[tagName] || !!unary;
124
+
125
+ if (!unary)
126
+ stack.push(tagName);
127
+
128
+ if (handler.start) {
129
+ var attrs = [];
130
+
131
+ rest.replace(attr, function(match, name) {
132
+ var value = arguments[2] ? arguments[2] :
133
+ arguments[3] ? arguments[3] :
134
+ arguments[4] ? arguments[4] :
135
+ fillAttrs[name] ? name : "";
136
+
137
+ attrs.push({
138
+ name: name,
139
+ value: value,
140
+ escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
141
+ });
142
+ });
143
+
144
+ if (handler.start)
145
+ handler.start(tagName, attrs, unary);
146
+ }
147
+ }
148
+
149
+ function parseEndTag(tag, tagName) {
150
+ // If no tag name is provided, clean shop
151
+ if (!tagName)
152
+ var pos = 0;
153
+
154
+ // Find the closest opened tag of the same type
155
+ else
156
+ for (var pos = stack.length - 1; pos >= 0; pos--)
157
+ if (stack[pos] == tagName)
158
+ break;
159
+
160
+ if (pos >= 0) {
161
+ // Close all the open elements, up the stack
162
+ for (var i = stack.length - 1; i >= pos; i--)
163
+ if (handler.end)
164
+ handler.end(stack[i]);
165
+
166
+ // Remove the open elements from the stack
167
+ stack.length = pos;
168
+ }
169
+ }
170
+ };
171
+
172
+ var HTMLtoXML = function(html) {
173
+ var results = "";
174
+
175
+ HTMLParser(html, {
176
+ start: function(tag, attrs, unary) {
177
+ results += "<" + tag;
178
+
179
+ for (var i = 0; i < attrs.length; i++)
180
+ results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';
181
+ results += ">";
182
+ },
183
+ end: function(tag) {
184
+ results += "</" + tag + ">";
185
+ },
186
+ chars: function(text) {
187
+ results += text;
188
+ },
189
+ comment: function(text) {
190
+ results += "<!--" + text + "-->";
191
+ }
192
+ });
193
+
194
+ return results;
195
+ };
196
+
197
+ var HTMLtoDOM = function(html, doc) {
198
+ // There can be only one of these elements
199
+ var one = makeMap("html,head,body,title");
200
+
201
+ // Enforce a structure for the document
202
+ var structure = {
203
+ link: "head",
204
+ base: "head"
205
+ };
206
+
207
+ if (!doc) {
208
+ if (typeof DOMDocument != "undefined")
209
+ doc = new DOMDocument();
210
+ else if (typeof document != "undefined" && document.implementation && document.implementation
211
+ .createDocument)
212
+ doc = document.implementation.createDocument("", "", null);
213
+ else if (typeof ActiveX != "undefined")
214
+ doc = new ActiveXObject("Msxml.DOMDocument");
215
+
216
+ } else
217
+ doc = doc.ownerDocument ||
218
+ doc.getOwnerDocument && doc.getOwnerDocument() ||
219
+ doc;
220
+
221
+ var elems = [],
222
+ documentElement = doc.documentElement ||
223
+ doc.getDocumentElement && doc.getDocumentElement();
224
+
225
+ // If we're dealing with an empty document then we
226
+ // need to pre-populate it with the HTML document structure
227
+ if (!documentElement && doc.createElement)(function() {
228
+ var html = doc.createElement("html");
229
+ var head = doc.createElement("head");
230
+ head.appendChild(doc.createElement("title"));
231
+ html.appendChild(head);
232
+ html.appendChild(doc.createElement("body"));
233
+ doc.appendChild(html);
234
+ })();
235
+
236
+ // Find all the unique elements
237
+ if (doc.getElementsByTagName)
238
+ for (var i in one)
239
+ one[i] = doc.getElementsByTagName(i)[0];
240
+
241
+ // If we're working with a document, inject contents into
242
+ // the body element
243
+ var curParentNode = one.body;
244
+
245
+ HTMLParser(html, {
246
+ start: function(tagName, attrs, unary) {
247
+ // If it's a pre-built element, then we can ignore
248
+ // its construction
249
+ if (one[tagName]) {
250
+ curParentNode = one[tagName];
251
+ if (!unary) {
252
+ elems.push(curParentNode);
253
+ }
254
+ return;
255
+ }
256
+
257
+ var elem = doc.createElement(tagName);
258
+
259
+ for (var attr in attrs)
260
+ elem.setAttribute(attrs[attr].name, attrs[attr].value);
261
+
262
+ if (structure[tagName] && typeof one[structure[tagName]] != "boolean")
263
+ one[structure[tagName]].appendChild(elem);
264
+
265
+ else if (curParentNode && curParentNode.appendChild)
266
+ curParentNode.appendChild(elem);
267
+
268
+ if (!unary) {
269
+ elems.push(elem);
270
+ curParentNode = elem;
271
+ }
272
+ },
273
+ end: function(tag) {
274
+ elems.length -= 1;
275
+
276
+ // Init the new parentNode
277
+ curParentNode = elems[elems.length - 1];
278
+ },
279
+ chars: function(text) {
280
+ curParentNode.appendChild(doc.createTextNode(text));
281
+ },
282
+ comment: function(text) {
283
+ // create comment node
284
+ }
285
+ });
286
+
287
+ return doc;
288
+ };
289
+
290
+ function makeMap(str) {
291
+ var obj = {},
292
+ items = str.split(",");
293
+ for (var i = 0; i < items.length; i++)
294
+ obj[items[i]] = true;
295
+ return obj;
296
+ }
297
+
298
+ function q(v) {
299
+ return '"' + v + '"';
300
+ }
301
+
302
+ function removeDOCTYPE(html) {
303
+ return html
304
+ .replace(/<\?xml.*\?>\n/, '')
305
+ .replace(/<!doctype.*\>\n/, '')
306
+ .replace(/<!DOCTYPE.*\>\n/, '');
307
+ }
308
+
309
+ function html2json(html) {
310
+ html = removeDOCTYPE(html);
311
+ var bufArray = [];
312
+ var results = {
313
+ node: 'root',
314
+ child: [],
315
+ };
316
+ HTMLParser(html, {
317
+ start: function(tag, attrs, unary) {
318
+ debug(tag, attrs, unary);
319
+ // node for this element
320
+ var node = {
321
+ node: 'element',
322
+ tag: tag,
323
+ };
324
+ if (attrs.length !== 0) {
325
+ node.attr = attrs.reduce(function(pre, attr) {
326
+ var name = attr.name;
327
+ var value = attr.value;
328
+
329
+ // has multi attibutes
330
+ // make it array of attribute
331
+ if (value.match(/ /)) {
332
+ value = value.split(' ');
333
+ }
334
+
335
+ // if attr already exists
336
+ // merge it
337
+ if (pre[name]) {
338
+ if (Array.isArray(pre[name])) {
339
+ // already array, push to last
340
+ pre[name].push(value);
341
+ } else {
342
+ // single value, make it array
343
+ pre[name] = [pre[name], value];
344
+ }
345
+ } else {
346
+ // not exist, put it
347
+ pre[name] = value;
348
+ }
349
+
350
+ return pre;
351
+ }, {});
352
+ }
353
+ if (unary) {
354
+ // if this tag dosen't have end tag
355
+ // like <img src="hoge.png"/>
356
+ // add to parents
357
+ var parent = bufArray[0] || results;
358
+ if (parent.child === undefined) {
359
+ parent.child = [];
360
+ }
361
+ parent.child.push(node);
362
+ } else {
363
+ bufArray.unshift(node);
364
+ }
365
+ },
366
+ end: function(tag) {
367
+ debug(tag);
368
+ // merge into parent tag
369
+ var node = bufArray.shift();
370
+ if (node.tag !== tag) console.error('invalid state: mismatch end tag');
371
+
372
+ if (bufArray.length === 0) {
373
+ results.child.push(node);
374
+ } else {
375
+ var parent = bufArray[0];
376
+ if (parent.child === undefined) {
377
+ parent.child = [];
378
+ }
379
+ parent.child.push(node);
380
+ }
381
+ },
382
+ chars: function(text) {
383
+ debug(text);
384
+ var node = {
385
+ node: 'text',
386
+ text: text,
387
+ };
388
+ if (bufArray.length === 0) {
389
+ results.child.push(node);
390
+ } else {
391
+ var parent = bufArray[0];
392
+ if (parent.child === undefined) {
393
+ parent.child = [];
394
+ }
395
+ parent.child.push(node);
396
+ }
397
+ },
398
+ comment: function(text) {
399
+ debug(text);
400
+ var node = {
401
+ node: 'comment',
402
+ text: text,
403
+ };
404
+ var parent = bufArray[0];
405
+ if (parent.child === undefined) {
406
+ parent.child = [];
407
+ }
408
+ parent.child.push(node);
409
+ },
410
+ });
411
+ return results;
412
+ };
413
+
414
+ function json2html(json) {
415
+ // Empty Elements - HTML 4.01
416
+ var empty = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta',
417
+ 'param', 'embed'
418
+ ];
419
+
420
+ var child = '';
421
+ if (json.child) {
422
+ child = json.child.map(function(c) {
423
+ return json2html(c);
424
+ }).join('');
425
+ }
426
+
427
+ var attr = '';
428
+ if (json.attr) {
429
+ attr = Object.keys(json.attr).map(function(key) {
430
+ var value = json.attr[key];
431
+ if (Array.isArray(value)) value = value.join(' ');
432
+ return key + '=' + q(value);
433
+ }).join(' ');
434
+ if (attr !== '') attr = ' ' + attr;
435
+ }
436
+
437
+ if (json.node === 'element') {
438
+ var tag = json.tag;
439
+ if (empty.indexOf(tag) > -1) {
440
+ // empty element
441
+ return '<' + json.tag + attr + '/>';
442
+ }
443
+
444
+ // non empty element
445
+ var open = '<' + json.tag + attr + '>';
446
+ var close = '</' + json.tag + '>';
447
+ return open + child + close;
448
+ }
449
+
450
+ if (json.node === 'text') {
451
+ return json.text;
452
+ }
453
+
454
+ if (json.node === 'comment') {
455
+ return '<!--' + json.text + '-->';
456
+ }
457
+
458
+ if (json.node === 'root') {
459
+ return child;
460
+ }
461
+ };
462
+
463
+ export {
464
+ html2json,
465
+ json2html
466
+ }
@@ -130,7 +130,7 @@
130
130
  </template>
131
131
 
132
132
  <script>
133
- import {html2json, json2html} from 'html2json'
133
+ import {html2json, json2html} from '@/components/utils/html2json.js'
134
134
  import svgs from './icon.vue'
135
135
 
136
136
  export default {
@@ -33,7 +33,7 @@
33
33
 
34
34
  <script>
35
35
  import exportWord from 'js-export-word'
36
- import {html2json, json2html} from 'html2json'
36
+ import {html2json, json2html} from '@/components/utils/html2json.js'
37
37
 
38
38
 
39
39
  export default {
package/src/index.js CHANGED
@@ -83,7 +83,7 @@ function install(app) {
83
83
  }
84
84
 
85
85
  export default {
86
- version: '1.33.334',
86
+ version: '1.33.336',
87
87
  install,
88
88
  Calendar,
89
89
  Message,