zydx-plus 1.33.449 → 1.34.451
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 +1 -1
- package/src/components/chat/index.js +6 -0
- package/src/components/chat/src/ai.png +0 -0
- package/src/components/chat/src/chat.vue +575 -0
- package/src/components/editor/src/editor.vue +17 -1
- package/src/components/editor2/src/editor.vue +15 -2
- package/src/components/paint/src/paint.vue +6 -1
- package/src/components/read/src/read.vue +25 -6
- package/src/index.js +6 -3
package/package.json
CHANGED
|
Binary file
|
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="chat-content"
|
|
3
|
+
:style="{
|
|
4
|
+
top: `${y !== '' ? `${y}px` : '50%'}`,
|
|
5
|
+
left: `${x !== '' ? `${x}px` : '50%'}`,
|
|
6
|
+
marginTop: `${y === ''? '-325px' : '0'}`,
|
|
7
|
+
marginLeft: `${x === ''? '-300px' : '0'}`,
|
|
8
|
+
}">
|
|
9
|
+
<div class="chat-header">
|
|
10
|
+
<span class="chat-header-title"
|
|
11
|
+
@mousedown.stop="chatMousedown"
|
|
12
|
+
@mouseup.stop="chatMouseup">
|
|
13
|
+
AI助手
|
|
14
|
+
</span>
|
|
15
|
+
<i class="iconfont zydx-guanbi" @click.stop="aiClose"></i>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="chat-in" ref="content">
|
|
18
|
+
<div class="chat-in-cont" ref="contentLi">
|
|
19
|
+
<div class="chat-in-li" :class="{'left': item.role === 'assistant', 'right': item.role === 'user'}" v-for="(item,index) in messages">
|
|
20
|
+
<div class="ai-avatar" v-if="item.role === 'assistant'">
|
|
21
|
+
<img src="./ai.png" alt="" />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="text-cont">{{ item.content }}</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="chat-input">
|
|
28
|
+
<div class="chat-text">
|
|
29
|
+
<textarea :disabled="disabled" @keydown="handleKeydown" v-model="userText" placeholder="请输入问题..."></textarea>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="chat-send">
|
|
32
|
+
<i @click="speak" :class="{'speak': microphone}" class="iconfont zydx-luyinhuatongmai"></i>
|
|
33
|
+
<button @click="send" :disabled="disabled" :class="{'disabled': disabled}">{{ disabled? '发送中...': '发送' }}</button>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="microphone" v-if="microphone">
|
|
37
|
+
<div class="microphone-cont mic-anim">
|
|
38
|
+
<div class="microphone1">
|
|
39
|
+
<div class="microphone2">
|
|
40
|
+
<div class="microphone3" @click="stopRecording">
|
|
41
|
+
<div>
|
|
42
|
+
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 38 68" width="26" height="48">
|
|
43
|
+
<path id="并集_轮廓_" data-name="并集 (轮廓)" fill="#ccc"
|
|
44
|
+
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"/>
|
|
45
|
+
<rect fill="#fff" x="11" y="4" width="16" height="36"/>
|
|
46
|
+
<rect class="volume" :height="volume(vol)" width="12" :y="volume2(vol)" x="13" fill="#43cf7c"/>
|
|
47
|
+
</svg>
|
|
48
|
+
</div>
|
|
49
|
+
<p>{{ voiceLoading? '语音转换中...': `正在说话:${countdown}s` }}</p>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<script>
|
|
59
|
+
import Recorder from 'js-audio-recorder'
|
|
60
|
+
import axios from 'axios'
|
|
61
|
+
export default {
|
|
62
|
+
name: 'zydx-chat',
|
|
63
|
+
data() {
|
|
64
|
+
return {
|
|
65
|
+
token: '',
|
|
66
|
+
messages: [],
|
|
67
|
+
userText: '',
|
|
68
|
+
disabled: false,
|
|
69
|
+
x: '',
|
|
70
|
+
y: '',
|
|
71
|
+
left: 0,
|
|
72
|
+
top: 0,
|
|
73
|
+
isMove: false,
|
|
74
|
+
microphone: false,
|
|
75
|
+
recorder: null,
|
|
76
|
+
countdown: 59,
|
|
77
|
+
fileSize: 0,
|
|
78
|
+
vol: 0,
|
|
79
|
+
base64: '',
|
|
80
|
+
voiceLoading: false
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
beforeUnmount() {
|
|
84
|
+
this.recorder.destroy()
|
|
85
|
+
},
|
|
86
|
+
mounted() {
|
|
87
|
+
const _this = this
|
|
88
|
+
this.init()
|
|
89
|
+
this.recorder.onprogress = function (params) {
|
|
90
|
+
if(_this.countdown <= 0) {
|
|
91
|
+
_this.stopRecording()
|
|
92
|
+
}else {
|
|
93
|
+
_this.countdown = 59 - parseInt(params.duration)
|
|
94
|
+
_this.vol = params.vol
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
document.addEventListener('mousemove', (e) => {
|
|
98
|
+
if (!this.isMove) return
|
|
99
|
+
this.x = e.clientX - this.left;
|
|
100
|
+
this.y = e.clientY - this.top;
|
|
101
|
+
// 超出边界
|
|
102
|
+
const w = document.documentElement.clientWidth;
|
|
103
|
+
const h = document.documentElement.clientHeight;
|
|
104
|
+
if (this.x < 0) {
|
|
105
|
+
this.x = 0;
|
|
106
|
+
}
|
|
107
|
+
if (this.y < 0) {
|
|
108
|
+
this.y = 0;
|
|
109
|
+
}
|
|
110
|
+
if (this.x > (w - 600)) {
|
|
111
|
+
this.x = w - 600;
|
|
112
|
+
}
|
|
113
|
+
if (this.y > (h - 650)) {
|
|
114
|
+
this.y = h - 650;
|
|
115
|
+
}
|
|
116
|
+
this.$emit('move', {x: this.x, y: this.y})
|
|
117
|
+
})
|
|
118
|
+
document.addEventListener('mouseup', (event) => {
|
|
119
|
+
this.isMove = false
|
|
120
|
+
})
|
|
121
|
+
},
|
|
122
|
+
watch: {
|
|
123
|
+
messages: {
|
|
124
|
+
handler: function (e, oldVal) {
|
|
125
|
+
sessionStorage.setItem('messages', JSON.stringify(e)) // 保存聊天记录
|
|
126
|
+
},
|
|
127
|
+
deep: true
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
methods: {
|
|
131
|
+
speak() {
|
|
132
|
+
if(this.disabled) return
|
|
133
|
+
this.microphone = !this.microphone
|
|
134
|
+
if(this.microphone) {
|
|
135
|
+
this.recorder.start().then(() => { // 开始录音
|
|
136
|
+
this.countdown = 59
|
|
137
|
+
this.fileSize = 0
|
|
138
|
+
this.vol = 0
|
|
139
|
+
this.base64 = ''
|
|
140
|
+
}, (error) => {
|
|
141
|
+
this.microphone = false
|
|
142
|
+
this.$message({
|
|
143
|
+
type: 'text',
|
|
144
|
+
cancelShow: false,
|
|
145
|
+
promptContent: '录音失败,请检查麦克风是否可用'
|
|
146
|
+
})
|
|
147
|
+
});
|
|
148
|
+
}else {
|
|
149
|
+
this.microphone = true
|
|
150
|
+
this.stopRecording()
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
stopRecording() {
|
|
154
|
+
this.recorder.stop() // 停止录音
|
|
155
|
+
// 获取录音文件
|
|
156
|
+
const pcm = this.recorder.getPCMBlob()
|
|
157
|
+
const file = new File([pcm], 'audio.pcm', {type: 'audio/pcm'})
|
|
158
|
+
let reader = new FileReader();
|
|
159
|
+
reader.readAsDataURL(file)
|
|
160
|
+
reader.onload = async () => {
|
|
161
|
+
this.base64 = reader.result.split('base64,')[1]
|
|
162
|
+
await this.getSpeech()
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
async getSpeech() {
|
|
166
|
+
const _this = this
|
|
167
|
+
const token = await this.getAccessToken('voice')
|
|
168
|
+
const data = {
|
|
169
|
+
format: "pcm",
|
|
170
|
+
rate: 16000,
|
|
171
|
+
channel: 1,
|
|
172
|
+
cuid: "Ukvpuzv27RdJhltQBlpITVLNTcxs5ctM",
|
|
173
|
+
token: token.data.data,
|
|
174
|
+
speech: this.base64,
|
|
175
|
+
len: this.recorder.fileSize,
|
|
176
|
+
};
|
|
177
|
+
_this.voiceLoading = true
|
|
178
|
+
axios.post('/server_api', data)
|
|
179
|
+
.then(function(data){
|
|
180
|
+
_this.voiceLoading = false
|
|
181
|
+
_this.microphone = false
|
|
182
|
+
for(let i=0; i< data.data.result.length; i++) {
|
|
183
|
+
_this.userText += data.data.result[i]
|
|
184
|
+
}
|
|
185
|
+
_this.recorder.destroy()
|
|
186
|
+
})
|
|
187
|
+
.catch(function(err){
|
|
188
|
+
_this.recorder.destroy()
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
volume(v) {
|
|
192
|
+
if(v === 0) {
|
|
193
|
+
return 32
|
|
194
|
+
}else {
|
|
195
|
+
return v/3 > 32 ? 32 : v/5
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
volume2(v) {
|
|
199
|
+
if(v === 0) {
|
|
200
|
+
return 6
|
|
201
|
+
}else {
|
|
202
|
+
return 6 + 32 - this.volume(v)
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
chatMousedown(event) {
|
|
206
|
+
event.preventDefault()
|
|
207
|
+
//鼠标按下事件
|
|
208
|
+
this.left = event.offsetX;
|
|
209
|
+
this.top = event.offsetY;
|
|
210
|
+
this.isMove = true
|
|
211
|
+
},
|
|
212
|
+
chatMouseup() {
|
|
213
|
+
this.isMove = false
|
|
214
|
+
},
|
|
215
|
+
// 监听键盘事件
|
|
216
|
+
handleKeydown(e) {
|
|
217
|
+
if(e.keyCode === 32){
|
|
218
|
+
e.preventDefault();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if(e.keyCode === 13){
|
|
222
|
+
e.preventDefault();
|
|
223
|
+
this.send()
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
// 滚动到底部
|
|
227
|
+
scrollToBottom() {
|
|
228
|
+
this.$nextTick(() => {
|
|
229
|
+
this.$refs.content.scrollTo(0,this.$refs.contentLi.scrollHeight)
|
|
230
|
+
})
|
|
231
|
+
},
|
|
232
|
+
// 发送消息
|
|
233
|
+
send() {
|
|
234
|
+
const _this = this
|
|
235
|
+
// 去掉换行和空格
|
|
236
|
+
let text = _this.userText.replace(/[\r\n]/g, '').replace(/\s*/g, '')
|
|
237
|
+
if(!text) return
|
|
238
|
+
_this.messages.push({
|
|
239
|
+
role: 'user',
|
|
240
|
+
content: text
|
|
241
|
+
})
|
|
242
|
+
_this.userText = ''
|
|
243
|
+
_this.disabled = true
|
|
244
|
+
_this.messages.push({
|
|
245
|
+
role: 'assistant',
|
|
246
|
+
content: '努力思考中...'
|
|
247
|
+
})
|
|
248
|
+
_this.scrollToBottom()
|
|
249
|
+
let mess = JSON.parse(JSON.stringify(_this.messages)) // 拷贝一份记录
|
|
250
|
+
mess.pop()
|
|
251
|
+
axios.post(`/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=${_this.token}`,{
|
|
252
|
+
messages: mess
|
|
253
|
+
}).then(function(data){
|
|
254
|
+
_this.messages.pop()
|
|
255
|
+
if(data.data.error_code){
|
|
256
|
+
_this.messages.push({
|
|
257
|
+
role: 'assistant',
|
|
258
|
+
content: '这个问题太难了!'
|
|
259
|
+
})
|
|
260
|
+
_this.disabled = false
|
|
261
|
+
_this.scrollToBottom()
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
_this.messages.push({
|
|
265
|
+
role: 'assistant',
|
|
266
|
+
content: data.data.result
|
|
267
|
+
})
|
|
268
|
+
_this.scrollToBottom()
|
|
269
|
+
_this.disabled = false
|
|
270
|
+
}).catch(function(err){
|
|
271
|
+
_this.disabled = false
|
|
272
|
+
this.$message({promptContent: err, cancelShow: false})
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
// 初始化
|
|
276
|
+
async init() {
|
|
277
|
+
this.messages = JSON.parse(sessionStorage.getItem('messages')) || []
|
|
278
|
+
this.scrollToBottom()
|
|
279
|
+
// 初始化录音
|
|
280
|
+
this.recorder = new Recorder({
|
|
281
|
+
sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
|
|
282
|
+
sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
|
|
283
|
+
numChannels: 1, // 声道,支持 1 或 2, 默认是1
|
|
284
|
+
})
|
|
285
|
+
const token = await this.getAccessToken('ai')
|
|
286
|
+
this.token = token.data.data
|
|
287
|
+
},
|
|
288
|
+
async getAccessToken(v) {
|
|
289
|
+
return axios({
|
|
290
|
+
url: '/zydx/voice/getBaiduToken',
|
|
291
|
+
method: 'post',
|
|
292
|
+
headers: {
|
|
293
|
+
'Authorization': localStorage.getItem('sessionId'),
|
|
294
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
295
|
+
},
|
|
296
|
+
params: {
|
|
297
|
+
type: v,
|
|
298
|
+
}
|
|
299
|
+
}).then(function(data){
|
|
300
|
+
return data
|
|
301
|
+
})
|
|
302
|
+
.catch(function(err){
|
|
303
|
+
console.log(err)
|
|
304
|
+
});
|
|
305
|
+
// return await getBaiduToken({type: v})
|
|
306
|
+
},
|
|
307
|
+
// 关闭
|
|
308
|
+
aiClose() {
|
|
309
|
+
this.$emit('close')
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
</script>
|
|
314
|
+
|
|
315
|
+
<style scoped>
|
|
316
|
+
.disabled{
|
|
317
|
+
background: #ccc !important;
|
|
318
|
+
}
|
|
319
|
+
.chat-content {
|
|
320
|
+
width: 600px;
|
|
321
|
+
height: 650px;
|
|
322
|
+
background: #fff;
|
|
323
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, .2);
|
|
324
|
+
position: fixed;
|
|
325
|
+
z-index: 10;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.chat-header {
|
|
329
|
+
height: 30px;
|
|
330
|
+
background: rgba(67, 207, 124, 1);
|
|
331
|
+
display: flex;
|
|
332
|
+
line-height: 30px;
|
|
333
|
+
padding: 0 10px;
|
|
334
|
+
box-sizing: border-box;
|
|
335
|
+
color: #fff;
|
|
336
|
+
font-size: 14px;
|
|
337
|
+
position: relative;
|
|
338
|
+
}
|
|
339
|
+
.chat-header-title{
|
|
340
|
+
cursor: move;
|
|
341
|
+
display: inline-block;
|
|
342
|
+
width: calc(100% - 30px);
|
|
343
|
+
margin-right: 30px;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.chat-header i {
|
|
347
|
+
cursor: pointer;
|
|
348
|
+
font-size: 18px;
|
|
349
|
+
position: absolute;
|
|
350
|
+
top: 0;
|
|
351
|
+
right: 10px;
|
|
352
|
+
z-index: 1;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.chat-in {
|
|
356
|
+
height: calc(100% - 112px);
|
|
357
|
+
overflow-y: auto;
|
|
358
|
+
transition: all 0.5s;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.chat-input {
|
|
362
|
+
height: 82px;
|
|
363
|
+
background: rgba(242, 242, 242, 1);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.chat-text {
|
|
367
|
+
width: 100%;
|
|
368
|
+
height: 55px;
|
|
369
|
+
padding: 5px;
|
|
370
|
+
box-sizing: border-box;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.chat-text textarea {
|
|
374
|
+
width: 100%;
|
|
375
|
+
height: 100%;
|
|
376
|
+
font-family: Helvetica, sans-serif;
|
|
377
|
+
border: none;
|
|
378
|
+
outline: none;
|
|
379
|
+
resize: none;
|
|
380
|
+
background: transparent;
|
|
381
|
+
font-size: 14px;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.chat-send {
|
|
385
|
+
padding: 0 5px 5px 5px;
|
|
386
|
+
height: 24px;
|
|
387
|
+
display: flex;
|
|
388
|
+
justify-content: space-between;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.chat-send i {
|
|
392
|
+
width: 24px;
|
|
393
|
+
display: inline-block;
|
|
394
|
+
height: 24px;
|
|
395
|
+
box-sizing: border-box;
|
|
396
|
+
border-radius: 50%;
|
|
397
|
+
border: 1px solid #ccc;
|
|
398
|
+
text-align: center;
|
|
399
|
+
line-height: 23px;
|
|
400
|
+
font-size: 14px;
|
|
401
|
+
background: #fff;
|
|
402
|
+
cursor: pointer;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.chat-send button {
|
|
406
|
+
background: rgba(67, 207, 124, 1);
|
|
407
|
+
border: none;
|
|
408
|
+
outline: none;
|
|
409
|
+
width: 70px;
|
|
410
|
+
height: 24px;
|
|
411
|
+
color: #fff;
|
|
412
|
+
font-size: 12px;
|
|
413
|
+
cursor: pointer;
|
|
414
|
+
border-radius: 3px;
|
|
415
|
+
text-align-last: justify;
|
|
416
|
+
word-break: break-all;
|
|
417
|
+
text-justify: distribute;
|
|
418
|
+
padding: 0 10px;
|
|
419
|
+
box-sizing: border-box;
|
|
420
|
+
}
|
|
421
|
+
.chat-in-cont{
|
|
422
|
+
padding: 5px 15px;
|
|
423
|
+
}
|
|
424
|
+
.chat-in-li{
|
|
425
|
+
padding: 10px 0;
|
|
426
|
+
}
|
|
427
|
+
.left{
|
|
428
|
+
position: relative;
|
|
429
|
+
min-height: 50px;
|
|
430
|
+
}
|
|
431
|
+
.left .text-cont{
|
|
432
|
+
box-shadow: 0 0 10px rgba(0,0,0,.2);
|
|
433
|
+
background: #fff;
|
|
434
|
+
margin-left: 60px;
|
|
435
|
+
}
|
|
436
|
+
.right{
|
|
437
|
+
text-align: right;
|
|
438
|
+
}
|
|
439
|
+
.right .text-cont{
|
|
440
|
+
background: #fff;
|
|
441
|
+
background: rgba(149, 236, 105, 1);
|
|
442
|
+
}
|
|
443
|
+
.text-cont{
|
|
444
|
+
padding: 10px;
|
|
445
|
+
border-radius: 5px;
|
|
446
|
+
display: inline-block;
|
|
447
|
+
text-align: justify !important;
|
|
448
|
+
max-width: 60%;
|
|
449
|
+
font-size: 14px;
|
|
450
|
+
line-height: 24px;
|
|
451
|
+
white-space: pre-line;
|
|
452
|
+
}
|
|
453
|
+
.ai-avatar{
|
|
454
|
+
position: absolute;
|
|
455
|
+
left: 0;
|
|
456
|
+
top: 10px;
|
|
457
|
+
width: 50px;
|
|
458
|
+
height: 50px;
|
|
459
|
+
border-radius: 50%;
|
|
460
|
+
overflow: hidden;
|
|
461
|
+
box-shadow: 0 0 10px rgba(0,0,0,.2);
|
|
462
|
+
background: #fff;
|
|
463
|
+
padding: 5px;
|
|
464
|
+
box-sizing: border-box;
|
|
465
|
+
}
|
|
466
|
+
.ai-avatar img{
|
|
467
|
+
width: 100%;
|
|
468
|
+
height: 100%;
|
|
469
|
+
}
|
|
470
|
+
.speak{
|
|
471
|
+
background: #43cf7c !important;
|
|
472
|
+
color: #fff !important;
|
|
473
|
+
border: 1px solid #43cf7c !important;
|
|
474
|
+
}
|
|
475
|
+
.microphone{
|
|
476
|
+
position: absolute;
|
|
477
|
+
left: 50%;
|
|
478
|
+
top: 50%;
|
|
479
|
+
z-index: 50;
|
|
480
|
+
width: 150px;
|
|
481
|
+
height: 150px;
|
|
482
|
+
transform: translate(-50%,-50%);
|
|
483
|
+
}
|
|
484
|
+
.microphone-cont{
|
|
485
|
+
width: 100%;
|
|
486
|
+
height: 100%;
|
|
487
|
+
border-radius: 50%;
|
|
488
|
+
position: relative;
|
|
489
|
+
}
|
|
490
|
+
.microphone1{
|
|
491
|
+
width: 100%;
|
|
492
|
+
height: 100%;
|
|
493
|
+
border-radius: 50%;
|
|
494
|
+
background: rgba(67, 207, 124, 0.3);
|
|
495
|
+
}
|
|
496
|
+
.microphone2{
|
|
497
|
+
width: calc(100% - 30px);
|
|
498
|
+
height: calc(100% - 30px);
|
|
499
|
+
border-radius: 50%;
|
|
500
|
+
background: rgba(67, 207, 124, 0.5);
|
|
501
|
+
position: absolute;
|
|
502
|
+
top: 50%;
|
|
503
|
+
left: 50%;
|
|
504
|
+
z-index: 1;
|
|
505
|
+
transform: translate(-50%,-50%);
|
|
506
|
+
}
|
|
507
|
+
.microphone3{
|
|
508
|
+
width: calc(100% - 30px);
|
|
509
|
+
height: calc(100% - 30px);
|
|
510
|
+
border-radius: 50%;
|
|
511
|
+
background: rgba(67, 207, 124, 0.8);
|
|
512
|
+
position: absolute;
|
|
513
|
+
top: 50%;
|
|
514
|
+
left: 50%;
|
|
515
|
+
z-index: 1;
|
|
516
|
+
transform: translate(-50%,-50%);
|
|
517
|
+
text-align: center;
|
|
518
|
+
padding-top: 10px;
|
|
519
|
+
box-sizing: border-box;
|
|
520
|
+
cursor: pointer;
|
|
521
|
+
}
|
|
522
|
+
.microphone3 p{
|
|
523
|
+
font-size: 12px;
|
|
524
|
+
color: #fff;
|
|
525
|
+
line-height: 18px;
|
|
526
|
+
}
|
|
527
|
+
.mic-anim .microphone1{
|
|
528
|
+
animation: mic-anim 1.5s infinite;
|
|
529
|
+
}
|
|
530
|
+
@keyframes mic-anim{
|
|
531
|
+
0%{
|
|
532
|
+
background: rgba(67, 207, 124, 0.2);
|
|
533
|
+
}
|
|
534
|
+
80%{
|
|
535
|
+
background: rgba(67, 207, 124, 0.4);
|
|
536
|
+
}
|
|
537
|
+
100%{
|
|
538
|
+
background: rgba(67, 207, 124, 0.2);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
.mic-anim .microphone2{
|
|
542
|
+
animation: mic-anim2 1.5s infinite;
|
|
543
|
+
}
|
|
544
|
+
@keyframes mic-anim2{
|
|
545
|
+
0%{
|
|
546
|
+
background: rgba(67, 207, 124, 0.4);
|
|
547
|
+
}
|
|
548
|
+
40%{
|
|
549
|
+
background: rgba(67, 207, 124, 0.6);
|
|
550
|
+
}
|
|
551
|
+
80%{
|
|
552
|
+
background: rgba(67, 207, 124, 0.4);
|
|
553
|
+
}
|
|
554
|
+
100%{
|
|
555
|
+
background: rgba(67, 207, 124, 0.4);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
.mic-anim .microphone3{
|
|
559
|
+
animation: mic-anim3 1.5s infinite;
|
|
560
|
+
}
|
|
561
|
+
@keyframes mic-anim3{
|
|
562
|
+
0%{
|
|
563
|
+
background: rgba(67, 207, 124, 0.8);
|
|
564
|
+
}
|
|
565
|
+
20%{
|
|
566
|
+
background: rgba(67, 207, 124, 1);
|
|
567
|
+
}
|
|
568
|
+
40%{
|
|
569
|
+
background: rgba(67, 207, 124, 0.8);
|
|
570
|
+
}
|
|
571
|
+
100%{
|
|
572
|
+
background: rgba(67, 207, 124, 0.8);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
</style>
|
|
@@ -58,6 +58,11 @@
|
|
|
58
58
|
<span :class="{'but-name-color':voiceOpen}" v-html="voiceOpen?'关闭语音':'语音输入'"></span>
|
|
59
59
|
</div>
|
|
60
60
|
</div>
|
|
61
|
+
<div v-if='isShowAiTool' class="editor-but">
|
|
62
|
+
<div class="editor-but-name" @click="showAi">
|
|
63
|
+
<span>AI助手</span>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
61
66
|
<!-- <div class="editor-but">
|
|
62
67
|
<div class="editor-but-name">
|
|
63
68
|
<label>
|
|
@@ -67,6 +72,7 @@
|
|
|
67
72
|
</div>
|
|
68
73
|
</div>-->
|
|
69
74
|
</div>
|
|
75
|
+
<zydx-chat v-if="isShowAi" @close='isShowAi = false'></zydx-chat>
|
|
70
76
|
<div :class="{'editor-content-show': !editableShow}" class="editor-content">
|
|
71
77
|
<div class="editing">
|
|
72
78
|
<div v-if="signMenuShow" class="editing-header">
|
|
@@ -615,6 +621,7 @@ import MarginStandard from "../src/margin-standard.vue";
|
|
|
615
621
|
import MarginWide from "../src/margin-wide.vue";
|
|
616
622
|
import isSelect from "../src/isSelect.vue";
|
|
617
623
|
import Paint from '../../paint/src/paint'
|
|
624
|
+
import zydxChat from '../../chat/src/chat.vue'
|
|
618
625
|
|
|
619
626
|
const img = require('./image/annotation.png')
|
|
620
627
|
export default {
|
|
@@ -632,6 +639,7 @@ export default {
|
|
|
632
639
|
zydxColoring,
|
|
633
640
|
zydxDragPopup,
|
|
634
641
|
zydxSelect,
|
|
642
|
+
zydxChat,
|
|
635
643
|
delSvg, editSvg, viewSvg,Paint
|
|
636
644
|
},
|
|
637
645
|
beforeUnmount() {
|
|
@@ -794,6 +802,7 @@ export default {
|
|
|
794
802
|
timeOut: null,
|
|
795
803
|
isShowPageMargin: false,
|
|
796
804
|
isShowHorizontalLine: false,
|
|
805
|
+
isShowAi: false,
|
|
797
806
|
isShowSwitchingFormat: false,
|
|
798
807
|
templateType: 'freeTypesetting',
|
|
799
808
|
switchingFormat: [
|
|
@@ -870,6 +879,10 @@ export default {
|
|
|
870
879
|
}
|
|
871
880
|
},
|
|
872
881
|
props: {
|
|
882
|
+
isShowAiTool: {
|
|
883
|
+
type: Boolean,
|
|
884
|
+
default: true
|
|
885
|
+
},
|
|
873
886
|
html: {
|
|
874
887
|
type: Array,
|
|
875
888
|
default: () => []
|
|
@@ -1346,6 +1359,9 @@ export default {
|
|
|
1346
1359
|
},
|
|
1347
1360
|
emits: ['confirm', 'enclosure', 'enlDownload', 'enlSee'],
|
|
1348
1361
|
methods: {
|
|
1362
|
+
showAi() {
|
|
1363
|
+
this.isShowAi = !this.isShowAi
|
|
1364
|
+
},
|
|
1349
1365
|
// 插入白板数据
|
|
1350
1366
|
exportImg(e) {
|
|
1351
1367
|
this.uploadFile(e, this.uploadImage).then(r => {
|
|
@@ -3723,8 +3739,8 @@ export default {
|
|
|
3723
3739
|
},
|
|
3724
3740
|
|
|
3725
3741
|
close() {
|
|
3726
|
-
if (this.ws === null) return
|
|
3727
3742
|
this.voiceOpen = false
|
|
3743
|
+
if (this.ws === null) return
|
|
3728
3744
|
this.ws?.send(JSON.stringify({"type": "CANCEL"}))
|
|
3729
3745
|
this.ws?.close()
|
|
3730
3746
|
this.ws = null
|
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
<button v-if="voiceShow" class="buts" @mousedown.stop="speechDown" @click="voice()"
|
|
20
20
|
:style="{color: (voiceStatus)? '#4B0C77' :'#000'}">{{ voiceStatus ? '关闭语音' : '语音输入' }}
|
|
21
21
|
</button>
|
|
22
|
+
<button v-if='isShowAiTool' class="buts" @click="showAi">AI助手</button>
|
|
22
23
|
</div>
|
|
23
24
|
</div>
|
|
25
|
+
<zydx-chat v-if="isShowAi" @close='isShowAi = false'></zydx-chat>
|
|
24
26
|
<div class="ed-cont" :style="heightStyleCont">
|
|
25
27
|
<div :style="{'border': (borderShow)? '1px solid #ccc': '0'}" v-if="editorShow">
|
|
26
28
|
<editor-content @paste.native.capture.prevent="preventPaste" ref="editorRef" class="editor" :editor="editor"
|
|
@@ -162,13 +164,16 @@ import alignmentModeCenter from './img/center.png'
|
|
|
162
164
|
import alignmentModeLeft from './img/left.png'
|
|
163
165
|
import alignmentModeRight from './img/right.png'
|
|
164
166
|
|
|
167
|
+
import zydxChat from '../../chat/src/chat.vue'
|
|
168
|
+
|
|
165
169
|
export default {
|
|
166
170
|
name: 'zydx-xiao-editor',
|
|
167
171
|
components: {
|
|
168
172
|
EditorContent,
|
|
169
173
|
BubbleMenu,
|
|
170
174
|
svgs,
|
|
171
|
-
Paint
|
|
175
|
+
Paint,
|
|
176
|
+
zydxChat
|
|
172
177
|
},
|
|
173
178
|
data() {
|
|
174
179
|
return {
|
|
@@ -202,7 +207,8 @@ export default {
|
|
|
202
207
|
editorRef: null,
|
|
203
208
|
imgSizeVal: '',
|
|
204
209
|
currentImgDom: {},
|
|
205
|
-
paintShow: false
|
|
210
|
+
paintShow: false,
|
|
211
|
+
isShowAi: false,
|
|
206
212
|
}
|
|
207
213
|
},
|
|
208
214
|
beforeUnmount() {
|
|
@@ -213,6 +219,10 @@ export default {
|
|
|
213
219
|
this.ws = null
|
|
214
220
|
},
|
|
215
221
|
props: {
|
|
222
|
+
isShowAiTool: {
|
|
223
|
+
type: Boolean,
|
|
224
|
+
default: true
|
|
225
|
+
},
|
|
216
226
|
titleVertical: {
|
|
217
227
|
type: Boolean,
|
|
218
228
|
default: false
|
|
@@ -419,6 +429,9 @@ export default {
|
|
|
419
429
|
})
|
|
420
430
|
},
|
|
421
431
|
methods: {
|
|
432
|
+
showAi() {
|
|
433
|
+
this.isShowAi = !this.isShowAi
|
|
434
|
+
},
|
|
422
435
|
exportImg(e) {
|
|
423
436
|
this.uploadFile(e, this.uploadImage).then(r => {
|
|
424
437
|
this.paintShow = false
|
|
@@ -236,6 +236,7 @@ export default {
|
|
|
236
236
|
},
|
|
237
237
|
emits: ['cancel','exportImg'],
|
|
238
238
|
created() {
|
|
239
|
+
stayTime = 0
|
|
239
240
|
this.ids = this.randomId()
|
|
240
241
|
},
|
|
241
242
|
mounted() {
|
|
@@ -551,8 +552,11 @@ export default {
|
|
|
551
552
|
this.top = e.clientY - this.topOffset;
|
|
552
553
|
},
|
|
553
554
|
mouseup(e) {
|
|
554
|
-
console.log(stayTime)
|
|
555
555
|
clearInterval(timer)
|
|
556
|
+
if (!this.pressDown) {
|
|
557
|
+
stayTime = 0
|
|
558
|
+
return
|
|
559
|
+
}
|
|
556
560
|
if (stayTime <= 100 && this.pressDown) { // 如果小于100就是点击事件
|
|
557
561
|
if (!this.toolArr[this.toolIndex]) {
|
|
558
562
|
stayTime = 0
|
|
@@ -583,6 +587,7 @@ export default {
|
|
|
583
587
|
return id.replace(/[0-9]/g, '')
|
|
584
588
|
},
|
|
585
589
|
cancel() {
|
|
590
|
+
stayTime = 0
|
|
586
591
|
document.body.style.overflow = 'visible'
|
|
587
592
|
this.$emit('cancel')
|
|
588
593
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="read">
|
|
3
3
|
<vue-office-docx v-if="fileType === 'docx'" :src="url" style="height: 100%;" @rendered="renderedHandler" @error="errorHandler" />
|
|
4
4
|
<vue-office-excel v-if="fileType === 'xlsx' && xlsx" :src="url" style="height: 100%;" @rendered="renderedHandler" @error="errorHandler" />
|
|
5
|
-
<div class="view-pdf" v-if="fileType === 'pdf'">
|
|
5
|
+
<div class="view-pdf" @scroll="scroll" v-if="fileType === 'pdf'">
|
|
6
6
|
<div class="pageContainer" v-for="(item,index) in idArr">
|
|
7
7
|
<canvas :id="item"></canvas>
|
|
8
8
|
<div class="pdfPage">{{ index + 1 }}/{{ pdfPages }}</div>
|
|
@@ -35,7 +35,7 @@ import '@vue-office/docx/lib/index.css'
|
|
|
35
35
|
import '@vue-office/excel/lib/index.css'
|
|
36
36
|
|
|
37
37
|
import Mess from '../../tipBox/index'
|
|
38
|
-
|
|
38
|
+
let pdfs = null
|
|
39
39
|
export default {
|
|
40
40
|
name: "zydx-read",
|
|
41
41
|
components: {VueOfficeDocx,VueOfficeExcel},
|
|
@@ -54,7 +54,8 @@ export default {
|
|
|
54
54
|
pdf: null,
|
|
55
55
|
page: 0,
|
|
56
56
|
xlsx: true,
|
|
57
|
-
canvasArr: []
|
|
57
|
+
canvasArr: [],
|
|
58
|
+
pageIndex: 0
|
|
58
59
|
}
|
|
59
60
|
},
|
|
60
61
|
props: {
|
|
@@ -148,10 +149,11 @@ export default {
|
|
|
148
149
|
cMapPacked: true
|
|
149
150
|
})
|
|
150
151
|
loadingTask.promise.then((pdf) => {
|
|
151
|
-
|
|
152
|
+
pdfs = pdf
|
|
152
153
|
that.pdfPages = pdf.numPages // 获取pdf文件的总页数
|
|
153
154
|
that.page = pdf.numPages
|
|
154
|
-
that.
|
|
155
|
+
that.pageIndex = that.page > 1? 2:1
|
|
156
|
+
that.getPDF(pdf,that.pageIndex)
|
|
155
157
|
}).catch(() => {
|
|
156
158
|
that.loading = false
|
|
157
159
|
Mess({
|
|
@@ -160,12 +162,29 @@ export default {
|
|
|
160
162
|
})
|
|
161
163
|
})
|
|
162
164
|
},
|
|
165
|
+
scroll(e) {
|
|
166
|
+
const dom = e.target
|
|
167
|
+
var scrollTop = dom.scrollTop; //滑入屏幕上方的高度
|
|
168
|
+
var windowHeitht = dom.clientHeight; //能看到的页面的高度
|
|
169
|
+
var scrollHeight = dom.scrollHeight; //监控的整个div的高度(包括现在看到的和上下隐藏起来看不到的)
|
|
170
|
+
let total = scrollTop + windowHeitht
|
|
171
|
+
if(total === scrollHeight){
|
|
172
|
+
if(this.pageIndex >= this.page) return
|
|
173
|
+
if((this.page - this.pageIndex) > 2) {
|
|
174
|
+
this.pageIndex += 2
|
|
175
|
+
this.getPDF(pdfs,2)
|
|
176
|
+
}else {
|
|
177
|
+
this.pageIndex += 1
|
|
178
|
+
this.getPDF(pdfs,1)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
163
182
|
getPDF(pdf,page) {
|
|
164
183
|
let that = this
|
|
165
184
|
for (let i = 0; i < page; i++) {
|
|
166
185
|
const id = 'canvas' + Math.random().toString(36).substr(2)
|
|
167
186
|
that.idArr.push(id)
|
|
168
|
-
pdf.getPage(
|
|
187
|
+
pdf.getPage(this.pageIndex === 1? 1:this.pageIndex + i - 1).then(function (page) {
|
|
169
188
|
let canvas = document.getElementById(id)
|
|
170
189
|
that.canvasArr.push(canvas)
|
|
171
190
|
let ctx = canvas.getContext('2d');
|
package/src/index.js
CHANGED
|
@@ -35,6 +35,7 @@ import question from './components/question/index';
|
|
|
35
35
|
import tagging from './components/tagging/index';
|
|
36
36
|
import seek from './components/seek/index';
|
|
37
37
|
import sketchpad from './components/sketchpad/index';
|
|
38
|
+
import chat from './components/chat/index';
|
|
38
39
|
|
|
39
40
|
const components = [
|
|
40
41
|
Calendar,
|
|
@@ -70,7 +71,8 @@ const components = [
|
|
|
70
71
|
question,
|
|
71
72
|
tagging,
|
|
72
73
|
seek,
|
|
73
|
-
sketchpad
|
|
74
|
+
sketchpad,
|
|
75
|
+
chat
|
|
74
76
|
];
|
|
75
77
|
|
|
76
78
|
function install(app) {
|
|
@@ -83,7 +85,7 @@ function install(app) {
|
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
export default {
|
|
86
|
-
version: '1.
|
|
88
|
+
version: '1.34.451',
|
|
87
89
|
install,
|
|
88
90
|
Calendar,
|
|
89
91
|
Message,
|
|
@@ -121,6 +123,7 @@ export default {
|
|
|
121
123
|
question,
|
|
122
124
|
tagging,
|
|
123
125
|
seek,
|
|
124
|
-
sketchpad
|
|
126
|
+
sketchpad,
|
|
127
|
+
chat
|
|
125
128
|
};
|
|
126
129
|
|