zydx-plus 1.32.256 → 1.32.258

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.256",
3
+ "version": "1.32.258",
4
4
  "description": "Vue.js",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -235,17 +235,17 @@ let buttonNames = {
235
235
  headLevel: {
236
236
  default: "demand",
237
237
  demand: '回答要求',
238
- singletonClass: this.getCurrentPrefix(item) + '项目',
238
+ singletonClass: this.getCurrentPrefix(item) + '追问',
239
239
  allClass: this.getPrefix(item) + '情况',
240
240
  },
241
241
  otherLevel: {
242
242
  default: "singletonClass",
243
- singletonClass: this.getCurrentPrefix(item) + '项目',
243
+ singletonClass: this.getCurrentPrefix(item) + '追问',
244
244
  allClass: this.getPrefix(item) + '情况',
245
245
  },
246
246
  lowLevel: {
247
247
  default: "singletonClass",
248
- singletonClass: this.getCurrentPrefix(item) + '项目',
248
+ singletonClass: this.getCurrentPrefix(item) + '追问',
249
249
  score: '回答成绩',
250
250
  analysis: '统计分析',
251
251
  power: '学习动力'
@@ -254,17 +254,17 @@ let buttonNames = {
254
254
  2: {
255
255
  headLevel: {
256
256
  default: "singletonClass",
257
- singletonClass: this.getCurrentPrefix(item) + '项目',
257
+ singletonClass: this.getCurrentPrefix(item) + '追问',
258
258
  allClass: this.getPrefix(item) + '情况',
259
259
  },
260
260
  otherLevel: {
261
261
  default: "singletonClass",
262
- singletonClass: this.getCurrentPrefix(item) + '项目',
262
+ singletonClass: this.getCurrentPrefix(item) + '追问',
263
263
  allClass: this.getPrefix(item) + '情况',
264
264
  },
265
265
  lowLevel: {
266
266
  default: "singletonClass",
267
- singletonClass: this.getCurrentPrefix(item) + '项目',
267
+ singletonClass: this.getCurrentPrefix(item) + '追问',
268
268
  score: '回答成绩',
269
269
  analysis: '统计分析',
270
270
  power: '学习动力'
@@ -1333,17 +1333,17 @@ let buttonNames = {
1333
1333
  headLevel: {
1334
1334
  default: "demand",
1335
1335
  demand: '回答要求',
1336
- singletonClass: this.getCurrentPrefix(item) + '项目',
1336
+ singletonClass: this.getCurrentPrefix(item) + '追问',
1337
1337
  allClass: this.getPrefix(item) + '情况',
1338
1338
  },
1339
1339
  otherLevel: {
1340
1340
  default: "singletonClass",
1341
- singletonClass: this.getCurrentPrefix(item) + '项目',
1341
+ singletonClass: this.getCurrentPrefix(item) + '追问',
1342
1342
  allClass: this.getPrefix(item) + '情况',
1343
1343
  },
1344
1344
  lowLevel: {
1345
1345
  default: "singletonClass",
1346
- singletonClass: this.getCurrentPrefix(item) + '项目',
1346
+ singletonClass: this.getCurrentPrefix(item) + '追问',
1347
1347
  score: '学习成绩',
1348
1348
  analysis: '统计分析',
1349
1349
  power: '学习动力'
@@ -46,13 +46,13 @@ export function butJson (editor,data) {
46
46
  name: '添加作者',
47
47
  key: 'authorMenu',
48
48
  menuKeys: [],
49
- html: `<p class="author" data-signId="author" style="text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 14px;">${menusData(data,'authorMenu').text}</span></p>`
49
+ html: `<p class="author" data-signId="author" style="text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 16px;font-family: KaiT;">${menusData(data,'authorMenu').text}</span></p>`
50
50
  },
51
51
  subjectMenu: {
52
52
  name: '添加题目',
53
53
  key: 'subjectMenu',
54
54
  menuKeys: [],
55
- html: `<p data-signId="subject" style="text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 24px;">${menusData(data,'subjectMenu').text}</span></p>`
55
+ html: `<p data-signId="subject" style="text-align: center;padding-bottom: 30px;"><span style="color: rgb(0, 0, 0);font-size: 24px;font-family: SimHei;font-weight: 700;">${menusData(data,'subjectMenu').text}</span></p>`
56
56
  },
57
57
  paragraphMenu: {
58
58
  name: '添加落款',
@@ -73,19 +73,19 @@ export function butJson (editor,data) {
73
73
  name: '关键词',
74
74
  key: 'keywordMenu',
75
75
  menuKeys: [],
76
- html: `<p class="keyword"><span style="color: rgb(0, 0, 0);font-size: 14px;font-weight: 700;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;关键词:</span><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi">关键词内容...</span></p>`
76
+ html: `<p class="keyword" data-signId="keyword"><span style="color: rgb(0, 0, 0);font-size: 12px;font-weight: 700;font-family: SimSun;">关键词:</span><span style="color: rgb(0, 0, 0);font-size: 12px;font-family: KaiTi">关键词内容...</span></p>`
77
77
  },
78
78
  abstractMenu: {
79
79
  name: '添加摘要',
80
80
  key: 'abstractMenu',
81
81
  menuKeys: [],
82
- html: `<p class="abstract"><span style="color: rgb(0, 0, 0);font-size: 14px;font-weight: 700;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;摘要:</span><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi">摘要内容...</span></p>`
82
+ html: `<p class="abstract" data-signId="abstract"><span style="color: rgb(0, 0, 0);font-size: 12px;font-weight: 700;font-family: SimSun;">摘要:</span><span style="color: rgb(0, 0, 0);font-size: 12px;font-family: KaiTi">摘要内容...</span></p>`
83
83
  },
84
84
  literatureMenu: {
85
85
  name: '添加文献',
86
86
  key: 'literatureMenu',
87
87
  menuKeys: [],
88
- html: `<p><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi">[1]作者.期刊论文名称IJ1.期刊名称,发表年份(第几期):页码</span></p><p><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi">[2]作者.学位论文名称[D1.毕业院校所在城市:毕业院校,论文提交年份:页码</span></p><p><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi">[3]作者.著作名称[M.出版社所在城市:出版社名称,出版年份:页码.</span></p><p data-signId="literature"><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi">[4]作者.文章名称[N].报纸名称,发行日期(版面)</span></p>`
88
+ html: `<p><span style="color: rgb(0, 0, 0);font-size: 12px;font-family: SimSun">[1]作者.期刊论文名称IJ1.期刊名称,发表年份(第几期):页码</span></p><p><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: SimSun">[2]作者.学位论文名称[D1.毕业院校所在城市:毕业院校,论文提交年份:页码</span></p><p><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: SimSun">[3]作者.著作名称[M.出版社所在城市:出版社名称,出版年份:页码.</span></p><p data-signId="literature"><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: SimSun">[4]作者.文章名称[N].报纸名称,发行日期(版面)</span></p>`
89
89
  },
90
90
  taggingMenu: {
91
91
  name: '添加标注',
@@ -104,8 +104,8 @@ export function butJson (editor,data) {
104
104
  key: 'ackMenu',
105
105
  menuKeys: [],
106
106
  html: [
107
- `<p data-signId="ack" contenteditable="false" style="text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 24px;font-weight: bold;">致谢</span></p>`,
108
- `<p><span style="color: rgb(0, 0, 0);font-size: 14px;">致谢内容...</span></p>`
107
+ `<p data-signId="ack" contenteditable="false" style="text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 16px;font-weight: bold;">致谢</span></p>`,
108
+ `<p><span style="color: rgb(0, 0, 0);font-size: 14px;font-family: KaiTi;">致谢内容...</span></p>`
109
109
  ]
110
110
  },
111
111
  'group-image': {
@@ -69,11 +69,6 @@
69
69
  <button class="but" @click="imgCancel">取消</button>
70
70
  </div>
71
71
  </div>
72
- <!-- <div v-if="loading" class="loading-back">-->
73
- <!-- <div class="loading-cont">-->
74
- <!-- <div class="loadings">Loading</div>-->
75
- <!-- </div>-->
76
- <!-- </div>-->
77
72
  <div class="down-html" id="test" v-html="htmlArr2"></div>
78
73
  </div>
79
74
  </template>
@@ -796,12 +791,14 @@ export default {
796
791
  // 关键词
797
792
  if (data.key === 'keywordMenu') {
798
793
  const html = butJson(this.editor, this.menusText)[data.key].html
799
- this.editor.chain().focus().insertContentAt(this.selection(), html).run()
794
+ const r = await this.signIdData('keyword')
795
+ if (r === -1) this.editor.chain().focus().insertContentAt(this.selection(), html).run()
800
796
  }
801
797
  // 摘要
802
798
  if (data.key === 'abstractMenu') {
803
799
  const html = butJson(this.editor, this.menusText)[data.key].html
804
- this.editor.chain().focus().insertContentAt(this.selection(), html).run()
800
+ const r = await this.signIdData('abstract')
801
+ if (r === -1) this.editor.chain().focus().insertContentAt(this.selection(), html).run()
805
802
  }
806
803
  // 致谢
807
804
  if (data.key === 'ackMenu') {
@@ -918,6 +915,12 @@ export default {
918
915
  .down-html :deep(img){
919
916
  padding: 5px 0;
920
917
  }
918
+ :deep(.keyword) {
919
+ text-indent: 2em;
920
+ }
921
+ :deep(.abstract) {
922
+ text-indent: 2em;
923
+ }
921
924
  .read-only {
922
925
  position: relative;
923
926
  margin: 0 auto;
@@ -925,7 +928,7 @@ export default {
925
928
 
926
929
  .read-only-page {
927
930
  width: 100%;
928
- padding: 100px;
931
+ padding: 120px 100px 66px 100px;
929
932
  background-color: #fff;
930
933
  box-sizing: border-box;
931
934
  position: relative;
@@ -944,13 +947,19 @@ export default {
944
947
  line-height: 24px;
945
948
  text-align: justify;
946
949
  }
950
+ :deep(p[data-signid="subject"]) {
951
+ padding-bottom: 30px;
952
+ }
953
+ :deep(.author){
954
+ padding-bottom: 40px;
955
+ }
947
956
  :deep(.text){
948
957
  text-indent: 2em;
949
958
  }
950
959
 
951
960
  .read-only-a {
952
961
  position: absolute;
953
- bottom: 70px;
962
+ bottom: 36px;
954
963
  left: 50%;
955
964
  z-index: 1;
956
965
  font-size: 14px;
@@ -1169,57 +1178,11 @@ li {
1169
1178
  }
1170
1179
 
1171
1180
  .editing-cont {
1172
- padding: 100px;
1181
+ padding: 120px 100px 66px 100px;
1173
1182
  box-sizing: border-box;
1174
1183
  width: 794px;
1175
1184
  min-height: 700px;
1176
1185
  }
1177
- .loading-back{
1178
- position: absolute;
1179
- top: 0;
1180
- left: 0;
1181
- right: 0;
1182
- bottom: 0;
1183
- z-index: 100;
1184
- display: flex;
1185
- align-items: center;
1186
- }
1187
- .loading-cont{
1188
- display: inline-block;
1189
- margin: 0 auto;
1190
- }
1191
- .loadings {
1192
- display: inline-block;
1193
- font-size: 28px;
1194
- font-family: Arial, Helvetica, sans-serif;
1195
- font-weight: bold;
1196
- color: #fff;
1197
- text-shadow: 0 0 2px #ff3d00, 0 0 1px #ff3d00, 0 0 1px #ff3d00;
1198
- letter-spacing: 2px;
1199
- position: relative;
1200
- }
1201
-
1202
- .loadings::after {
1203
- content: "Loading";
1204
- position: absolute;
1205
- left: 0;
1206
- top: 0;
1207
- color: #ff3d00;
1208
- width: 0%;
1209
- height: 100%;
1210
- overflow: hidden;
1211
- animation: loading-animation 6s linear infinite;
1212
- }
1213
-
1214
- @keyframes loading-animation {
1215
- 0% {
1216
- width: 0;
1217
- }
1218
-
1219
- 100% {
1220
- width: 100%;
1221
- }
1222
- }
1223
1186
  .menu{
1224
1187
  background-color: #fff;
1225
1188
  padding: 5px;
@@ -23,7 +23,16 @@
23
23
  </div>
24
24
  <div class="ed-cont" :style="heightStyleCont">
25
25
  <div :style="{'border': (borderShow)? '1px solid #ccc': '0'}" v-if="editorShow">
26
- <editor-content ref="editorRef" class="editor" :editor="editor" :style="heightStyleCont"/>
26
+ <editor-content @paste.native.capture.prevent="preventPaste" ref="editorRef" class="editor" :editor="editor"
27
+ :style="heightStyleCont"/>
28
+ </div>
29
+ <div v-if="voiceStatus" class="speak">
30
+ <div class="speak-cont">
31
+ <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>
32
+ <svgs :vol="vol"></svgs>
33
+ <span>{{ error? '开启语音失败' : '正在说话...' }}</span>
34
+ <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>
35
+ </div>
27
36
  </div>
28
37
  <div class="editor-but" v-if="butText !== '' && readOnly">
29
38
  <button class="buts" @click="complete">{{ butText }}</button>
@@ -80,34 +89,10 @@
80
89
  </div>
81
90
  </div>
82
91
  </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>
106
92
  </div>
107
93
  </template>
108
94
  <script>
109
95
  import Recorder from 'js-audio-recorder'
110
- import axios from 'axios'
111
96
  import zydxTextarea from '../../textarea/src/textarea'
112
97
  import {html2json, json2html} from 'html2json'
113
98
  import {Editor, EditorContent} from '@tiptap/vue-3'
@@ -120,7 +105,7 @@ import textStyle from '@tiptap/extension-text-style'
120
105
  import {sid} from "./sign-id";
121
106
  import {FontSize} from "./font-size";
122
107
  import {titleId} from "./title-id";
123
- import svgs from "./microphone";
108
+ import svgs from "./level";
124
109
 
125
110
  export default {
126
111
  name: 'zydx-xiao-editor',
@@ -137,20 +122,20 @@ export default {
137
122
  heightStyleCont: {},
138
123
  voiceStatus: false,
139
124
  recorder: null,
140
- drawRecordId: null,
141
- recordingStatus: false,
142
- countdown: 59,
143
- fileSize: 0,
125
+ ws: null,
126
+ audioContext: null,
127
+ audioData: [],
144
128
  vol: 0,
145
- base64: '',
146
- voiceContent: '',
147
- voiceLoading: false,
148
- textEditing: false
129
+ appData: {},
130
+ error: false,
131
+ time: {}
149
132
  }
150
133
  },
151
134
  beforeUnmount() {
152
- this.editor.destroy()
153
- this.recorder.destroy()
135
+ this.editor?.destroy()
136
+ this.recorder?.destroy()
137
+ this.ws?.send(JSON.stringify({"type":"CANCEL"}))
138
+ this.ws?.close()
154
139
  },
155
140
  props: {
156
141
  data: {
@@ -271,6 +256,7 @@ export default {
271
256
  this.editor = new Editor({
272
257
  content: json2html({node: "root", child: (this.data.html === undefined || null) ? [] : this.data.html}),
273
258
  editable: this.readOnly,
259
+ enablePasteRules: true,
274
260
  extensions: [
275
261
  sid,
276
262
  StarterKit,
@@ -311,16 +297,7 @@ export default {
311
297
  }
312
298
  }
313
299
  })
314
- // 处理粘贴事件
315
- this.$refs.editorRef.$el.addEventListener('paste', (event) => {
316
- event.preventDefault();
317
- const text = event.clipboardData.getData('text/plain');
318
- const index = this.editor.state.selection.$anchor.path[1]
319
- this.editor.chain().focus().insertContentAt(this.selection(), `<p>${text}</p>`).run()
320
- const json = this.editor.getJSON()
321
- json.content.splice(index, 1)
322
- this.editor?.commands.setContent(json)
323
- })
300
+ _this.appID()
324
301
  // 初始化录音
325
302
  this.recorder = new Recorder({
326
303
  sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
@@ -328,116 +305,152 @@ export default {
328
305
  numChannels: 1, // 声道,支持 1 或 2, 默认是1
329
306
  })
330
307
  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
- }
308
+ _this.vol = params.vol
338
309
  }
339
310
  },
340
311
  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>`
312
+ // 粘贴文本处理
313
+ preventPaste(event) {
314
+ const text = event.clipboardData.getData('text/plain');
315
+ const text2 = text.replace(/[\r\n]/g, '').replace(/\s*/g, '')
316
+ this.editor.chain().focus().insertContentAt(this.selection(), text2).run()
317
+ },
318
+ to16kHz(audioData, sampleRate = 44100) {
319
+ const data = new Float32Array(audioData);
320
+ const fitCount = Math.round(data.length * (16000 / sampleRate));
321
+ const newData = new Float32Array(fitCount);
322
+ const springFactor = (data.length - 1) / (fitCount - 1);
323
+ newData[0] = data[0];
324
+ for (let i = 1; i < fitCount - 1; i++) {
325
+ const tmp = i * springFactor;
326
+ const before = Math.floor(tmp).toFixed();
327
+ const after = Math.ceil(tmp).toFixed();
328
+ const atPoint = tmp - before;
329
+ newData[i] = data[before] + (data[after] - data[before]) * atPoint;
347
330
  }
348
- this.editor.commands.setContent(editorHtml.replace(/<p><\/p>/g, ''))
349
- },
350
- editingCancel() {
351
- this.textEditing = false
331
+ newData[fitCount - 1] = data[data.length - 1];
332
+ return newData;
333
+ },
334
+ to16BitPCM(input) {
335
+ const dataLength = input.length * (16 / 8);
336
+ const dataBuffer = new ArrayBuffer(dataLength);
337
+ const dataView = new DataView(dataBuffer);
338
+ let offset = 0;
339
+ for (let i = 0; i < input.length; i++, offset += 2) {
340
+ const s = Math.max(-1, Math.min(1, input[i]));
341
+ dataView.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
342
+ }
343
+ return dataView;
344
+ },
345
+ getAudioSuccess() {
346
+ let that = this
347
+ const mediaStreamSource = that.recorder.audioInput
348
+ // 创建一个音频分析对象,采样的缓冲区大小为0(自动适配),输入和输出都是单声道
349
+ const scriptProcessor = that.recorder.context.createScriptProcessor(1024, 1, 1);
350
+ scriptProcessor.onaudioprocess = (e) => {
351
+ // 去处理音频数据
352
+ const inputData = e.inputBuffer.getChannelData(0)
353
+ const output = that.to16kHz(inputData, that.recorder.context.sampleRate);
354
+ const audioData = that.to16BitPCM(output);
355
+ that.audioData.push(...new Int8Array(audioData.buffer));
356
+ if (that.audioData.length > 10240) {
357
+ const audioDataArray = new Int8Array(that.audioData);
358
+ that.ws.send(audioDataArray)
359
+ that.audioData = [];
360
+ }
361
+ }
362
+ mediaStreamSource.connect(scriptProcessor);
363
+ scriptProcessor.connect(that.recorder.context.destination);
352
364
  },
353
- // 语音输入
354
365
  voice() {
355
- this.voiceStatus = !this.voiceStatus
356
- this.recorder.stop() // 停止录音
357
- this.recorder.destroy() // 销毁录音
358
- },
359
- startVoice() {
360
- if (!this.recordingStatus) {
366
+ let that = this
367
+ that.voiceStatus = !this.voiceStatus
368
+ if(that.voiceStatus) {
361
369
  this.recorder.start().then(() => { // 开始录音
362
- this.fileSize = 0
363
- this.recordingStatus = true
370
+ this.audioData = []
371
+ this.webSocketInit()
364
372
  }, (error) => {
365
- this.recordingStatus = false
373
+ this.$message({
374
+ type: 'text',
375
+ cancelShow: false,
376
+ promptContent: '录音失败,请检查麦克风是否可用'
377
+ })
366
378
  });
367
- } else {
368
- this.stopRecording()
379
+ }else {
380
+ that.close()
369
381
  }
370
382
  },
371
- stopRecording() {
383
+ close() {
384
+ this.voiceStatus = false
385
+ this.ws.send(JSON.stringify({"type":"CANCEL"}))
386
+ this.ws.close()
372
387
  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
- }
388
+ this.recorder.destroy()
384
389
  },
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')
390
+ webSocketInit() {
391
+ const _this = this
392
+ _this.ws = new WebSocket(`wss://vop.baidu.com/realtime_asr?sn=${this.getRandomCode(15)}`)
393
+ _this.ws.binaryType = 'arraybuffer'
394
+ _this.ws.onopen = function () {
395
+ _this.error = false
396
+ const json = {
397
+ type: 'START',
398
+ data: {
399
+ appid: Number(_this.appData.qfClientId),
400
+ appkey: _this.appData.qfClientSecret,
401
+ dev_pid: 15372,
402
+ cuid: 'HpURryNC91ddJmAPq7iwu26OvMDW4jMS',
403
+ format: 'pcm',
404
+ sample: 16000,
405
+ }
393
406
  }
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
- }
407
+ _this.ws.send(JSON.stringify(json))
408
+ _this.getAudioSuccess()
409
+ }
410
+ _this.ws.onmessage = function (e) {
411
+ const data = JSON.parse(e.data)
412
+ if(data.err_no === 0){
413
+ const json = _this.editor.getJSON()
414
+ const index = _this.editor.state.selection.$anchor.path[1]
415
+ if(data.start_time === _this.time.start_time) {
416
+ const text = json.content[index].content[0].text
417
+ json.content[index].content[0].text = text.slice(0, text.length - _this.time.result.length) + data.result
418
+ _this.editor.commands.setContent(json)
419
+ }else {
420
+ _this.editor.chain().focus().insertContentAt(_this.selection(), data.result).run()
406
421
  }
422
+ _this.time = data
407
423
  }
408
- xhr.send(params)
409
- })
424
+ }
425
+ _this.ws.onerror = function () {
426
+ // 连接失败重连
427
+ setTimeout(() => {
428
+ _this.error = true
429
+ _this.webSocketInit()
430
+ }, 5000)
431
+ }
410
432
  },
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
- });
433
+ appID() {
434
+ let token = null
435
+ let remember = localStorage.getItem('remember')
436
+ if(remember === '1') {
437
+ token = localStorage.getItem('sessionId')
438
+ }else {
439
+ token = sessionStorage.getItem('sessionId')
440
+ }
441
+ const xhr = new XMLHttpRequest()
442
+ // xhr.open('GET', 'http://192.168.15.126:8888/zydx/voice/getDesKeyId')
443
+ // xhr.setRequestHeader('Authorization', 'e891f5a9-4cf0-4f9f-b969-c91d44e6648c')
444
+ xhr.open('GET', '/zydx/voice/getDesKeyId')
445
+ xhr.setRequestHeader('Authorization', token)
446
+ xhr.onreadystatechange = () => {
447
+ if (xhr.readyState === 4) {
448
+ if (xhr.status === 200) {
449
+ this.appData = JSON.parse(xhr.responseText).data
450
+ }
451
+ }
452
+ }
453
+ xhr.send()
441
454
  },
442
455
  enclosureAction(v) {
443
456
  return v.map(x => {
@@ -623,6 +636,19 @@ export default {
623
636
  if (v === 'centerH2') this.editor.chain().focus().setFontSize('16px').setBold().setTextAlign('center').run()
624
637
  if (v === 'leftH2') this.editor.chain().focus().setFontSize('16px').setBold().setTextAlign('left').run()
625
638
  if (v === 'rightH2') this.editor.chain().focus().setFontSize('16px').setBold().setTextAlign('right').run()
639
+ },
640
+ getRandomCode(length) {
641
+ if (length > 0) {
642
+ 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"];
643
+ let nums = "";
644
+ for (let i = 0; i < length; i++) {
645
+ let r = parseInt(Math.random() * 61);
646
+ nums += data[r];
647
+ }
648
+ return nums.replace(/(.{4})/g, "$1-");
649
+ } else {
650
+ return false;
651
+ }
626
652
  }
627
653
  }
628
654
  }
@@ -630,142 +656,33 @@ export default {
630
656
  </script>
631
657
 
632
658
  <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;
659
+ .speak{
660
+ text-align: right;
661
+ padding: 5px 0;
647
662
  }
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;
663
+ .speak-cont{
664
+ background: rgba(67, 207, 124, 1);
665
+ color: #fff;
666
+ padding: 0 10px;
667
+ height: 30px;
668
+ line-height: 30px;
655
669
  display: inline-block;
670
+ border-radius: 20px;
656
671
  }
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;
672
+ .speak-cont svg{
673
+ vertical-align: middle;
674
+ margin-top: -3px;
695
675
  }
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;
676
+ .speak-cont span{
677
+ font-size: 14px;
678
+ padding: 0 5px;
761
679
  }
762
- .microphone-text{
763
- text-align: center;
764
- margin-top: 12px;
765
- font-size: 18px;
766
- line-height: 26px;
680
+ .text-editing-cont p {
681
+ font-size: 16px;
682
+ line-height: 24px;
767
683
  font-weight: 700;
768
684
  }
685
+
769
686
  :deep(.imgCont) {
770
687
  line-height: 0 !important;
771
688
  }
@@ -934,6 +851,7 @@ export default {
934
851
  display: inline-block;
935
852
  position: relative;
936
853
  }
854
+
937
855
  .schedule span {
938
856
  font-size: 12px;
939
857
  position: absolute;
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14"
3
+ viewBox="0 0 16 16" fill="none">
4
+ <g opacity="1" transform="translate(0 0) rotate(0)">
5
+ <mask id="bg-mask-0" fill="white">
6
+ <use transform="translate(0 0) rotate(0)" xlink:href="#path_0"></use>
7
+ </mask>
8
+ <g mask="url(#bg-mask-0)">
9
+ <rect :fill="volFill(vol,1)" x="1" y="12" width="2" height="5"/>
10
+ <rect :fill="volFill(vol,2)" x="5" y="8" width="2" height="9"/>
11
+ <rect :fill="volFill(vol,3)" x="9" y="4" width="2" height="13"/>
12
+ <rect :fill="volFill(vol,4)" x="13" y="0" width="2" height="17"/>
13
+ </g>
14
+ </g>
15
+ <defs>
16
+ <rect id="path_0" x="0" y="0" width="16" height="16"/>
17
+ </defs>
18
+ </svg>
19
+ </template>
20
+
21
+ <script>
22
+ export default {
23
+ props: {
24
+ vol: {
25
+ type: Number,
26
+ default: 0
27
+ }
28
+ },
29
+ methods: {
30
+ volFill(v,n) {
31
+ v = Math.floor(v)
32
+ if(n === 1) {
33
+ if(v >= 10) {
34
+ return '#fff'
35
+ } else {
36
+ return '#12A64D'
37
+ }
38
+ } else if(n === 2) {
39
+ if(v >= 25) {
40
+ return '#fff'
41
+ } else {
42
+ return '#12A64D'
43
+ }
44
+ } else if(n === 3) {
45
+ if(v >= 35) {
46
+ return '#fff'
47
+ } else {
48
+ return '#12A64D'
49
+ }
50
+ } else if(n === 4) {
51
+ if(v >= 45) {
52
+ return '#fff'
53
+ } else {
54
+ return '#12A64D'
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+ </script>
61
+
62
+ <style scoped>
63
+
64
+ </style>
@@ -31,7 +31,7 @@
31
31
  <script>
32
32
  import * as PdfJs from 'pdfjs-dist/legacy/build/pdf.js' // 注意导入的写法d
33
33
  PdfJs.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.entry')
34
- const jsdelivr = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/'
34
+ const jsdelivr = '/zydx/static/cmaps/'
35
35
  export default {
36
36
  name: "zydx-flip",
37
37
  data() {
@@ -95,7 +95,7 @@ export default {
95
95
  let that = this
96
96
  const loadingTask = PdfJs.getDocument({
97
97
  url: this.url,
98
- cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.2.228/cmaps/",
98
+ cMapUrl: "/zydx/static/cmaps/",
99
99
  cMapPacked: true
100
100
  })
101
101
  loadingTask.promise.then((pdf) => {
package/src/index.js CHANGED
@@ -79,7 +79,7 @@ function install(app) {
79
79
  }
80
80
 
81
81
  export default {
82
- version: '1.32.256',
82
+ version: '1.32.258',
83
83
  install,
84
84
  Calendar,
85
85
  Message,
@@ -1,47 +0,0 @@
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>