zydx-plus 1.35.543 → 1.35.545
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
|
Binary file
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="docView" @mouseleave="mouseUpTest" @mouseup="mouseUpTest">
|
|
2
|
+
<div class="docView" @click="extendRightDel" @mouseleave="mouseUpTest" @mouseup="mouseUpTest">
|
|
3
3
|
<div class="full-screen" v-if="false">
|
|
4
4
|
<div class="full-screen-img" @click.stop="fullScreen">
|
|
5
5
|
<!-- <div class="full-screen-title" style="" v-if="showText">全屏查看</div>-->
|
|
@@ -19,18 +19,30 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
21
|
<div>
|
|
22
|
-
<div class="book" ref="book">
|
|
22
|
+
<div class="book" ref="book" @click.right="rightMenu($event)">
|
|
23
23
|
<div class="pages">
|
|
24
24
|
<div class="wrap-box" ref="wrap-box" v-show="doublePage">
|
|
25
25
|
<div class="wrap wrap-block" :ref="`wrap-${item.id}`" v-for="(item,index) in pageInfoArr" :key="index">
|
|
26
26
|
<div class="wrap-can" v-show="!loading" ref="wrapCanBox">
|
|
27
|
+
<div class="extend-right" v-if="rightMenuShow" :style="extendStyle">
|
|
28
|
+
<p @click.stop="extendRight(index)">链接扩展</p>
|
|
29
|
+
</div>
|
|
27
30
|
<div class="textLayer" ref="textLayer">
|
|
28
31
|
<span :dir="item2.dir" :style="styleText(item2,item.styles, item.id)" v-for="(item2) in item.items">{{ item2.str }}</span>
|
|
29
32
|
</div>
|
|
30
33
|
<div class="annotationLayer" ref="annotationLayer">
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
+
<template v-for="(item,index) in annotations">
|
|
35
|
+
<div :style="styleAnnotation(item)" class="magnifier" v-if="item.type === 'tag'">
|
|
36
|
+
<img @click.stop="magnifierTap($event,item)" src="../img/fangdajing.png" alt="" />
|
|
37
|
+
<div class="magnifier-list" v-if="item.show" :style="item.style">
|
|
38
|
+
<div class="magnifier-list-item" @click="annotationTap(item2)" v-for="(item2,index2) in item.list">{{ index2+1 }}.{{ item2?.title }}</div>
|
|
39
|
+
<div class="magnifier-list-add" @click="annotationTap(item,'add')">添加扩展链接</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
<section v-else tabindex="1000" @click="annotationTap(item,item.id)" :style="styleAnnotation(item)">
|
|
43
|
+
<a :href="item.url" target="_blank"></a>
|
|
44
|
+
</section>
|
|
45
|
+
</template>
|
|
34
46
|
</div>
|
|
35
47
|
<canvas @click.stop="turnText" class="wrap-can-one" :class="{isPointer: isPointer}" @mousedown.stop="mouseDown"
|
|
36
48
|
@mousemove.stop="mouseMove" :id="item.id"></canvas>
|
|
@@ -55,13 +67,25 @@
|
|
|
55
67
|
</div>
|
|
56
68
|
<div class="wrap" ref="wrap" v-show="!doublePage">
|
|
57
69
|
<div class="wrap-can" v-show="!loading" ref="wrapCan">
|
|
70
|
+
<div class="extend-right" v-if="rightMenuShow" :style="extendStyle">
|
|
71
|
+
<p @click.stop="extendRight(null)">链接扩展</p>
|
|
72
|
+
</div>
|
|
58
73
|
<div class="textLayer" ref="textLayer">
|
|
59
74
|
<span :dir="item.dir" :style="styleText(item,styles)" v-for="(item,index) in items">{{ item.str }}</span>
|
|
60
75
|
</div>
|
|
61
76
|
<div class="annotationLayer" ref="annotationLayer">
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
|
|
77
|
+
<template v-for="(item,index) in annotations">
|
|
78
|
+
<div :style="styleAnnotation(item)" class="magnifier" v-if="item.type === 'tag'">
|
|
79
|
+
<img @click.stop="magnifierTap($event,item)" src="../img/fangdajing.png" alt="" />
|
|
80
|
+
<div class="magnifier-list" v-if="item.show" :style="item.style">
|
|
81
|
+
<div class="magnifier-list-item" @click="annotationTap(item2)" v-for="(item2,index2) in item.list">{{ index2+1 }}.{{ item2?.title }}</div>
|
|
82
|
+
<div class="magnifier-list-add" @click="annotationTap(item,'add')">添加扩展链接</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<section v-else tabindex="1000" @click="annotationTap(item)" :style="styleAnnotation(item)">
|
|
86
|
+
<a :href="item.url" target="_blank"></a>
|
|
87
|
+
</section>
|
|
88
|
+
</template>
|
|
65
89
|
</div>
|
|
66
90
|
<canvas @click.stop="turnText" class="wrap-can-one" :class="{isPointer: isPointer}" @mousedown.stop="mouseDown"
|
|
67
91
|
@mousemove.stop="mouseMove" :id="`${id}`"></canvas>
|
|
@@ -121,7 +145,7 @@ import * as PdfJs from 'pdfjs-dist'
|
|
|
121
145
|
import "pdfjs-dist/build/pdf.worker.mjs";
|
|
122
146
|
import Range from "../../tagging/src/range";
|
|
123
147
|
|
|
124
|
-
let pdfs =
|
|
148
|
+
let pdfs = {};
|
|
125
149
|
|
|
126
150
|
export default {
|
|
127
151
|
name: "zydx-flip",
|
|
@@ -195,7 +219,13 @@ export default {
|
|
|
195
219
|
viewWidth: 0,
|
|
196
220
|
viewHeight: 0,
|
|
197
221
|
annotations: [],
|
|
198
|
-
|
|
222
|
+
annotationsInit: [],
|
|
223
|
+
extendStyle: {
|
|
224
|
+
left: '0px',
|
|
225
|
+
top: '0px'
|
|
226
|
+
},
|
|
227
|
+
rightMenuShow: false,
|
|
228
|
+
annData: {}
|
|
199
229
|
}
|
|
200
230
|
},
|
|
201
231
|
props: {
|
|
@@ -252,11 +282,23 @@ export default {
|
|
|
252
282
|
watch: {
|
|
253
283
|
annotationsData: {
|
|
254
284
|
handler: function (val) {
|
|
255
|
-
console.log(val)
|
|
256
285
|
if(typeof val === Object) {
|
|
257
|
-
this.annotations.push(
|
|
286
|
+
this.annotations.push({
|
|
287
|
+
...val,
|
|
288
|
+
show: false,
|
|
289
|
+
style: {},
|
|
290
|
+
type: "tag"
|
|
291
|
+
})
|
|
258
292
|
}else {
|
|
259
|
-
|
|
293
|
+
const arr = val.map(x => {
|
|
294
|
+
return {
|
|
295
|
+
...x,
|
|
296
|
+
show: false,
|
|
297
|
+
style: {},
|
|
298
|
+
type: "tag"
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
this.annotations = arr.concat(this.annotationsInit)
|
|
260
302
|
}
|
|
261
303
|
},
|
|
262
304
|
deep: true,
|
|
@@ -334,9 +376,8 @@ export default {
|
|
|
334
376
|
immediate: true
|
|
335
377
|
}
|
|
336
378
|
},
|
|
337
|
-
emits: ['flip','annotationTap'],
|
|
379
|
+
emits: ['flip','annotationTap', 'annotationsSend'],
|
|
338
380
|
mounted() {
|
|
339
|
-
this.inits = true
|
|
340
381
|
if (!this.doublePage) {
|
|
341
382
|
this.id = 'canvas-wrap' + this.generateUniqueKey()
|
|
342
383
|
}
|
|
@@ -353,12 +394,86 @@ export default {
|
|
|
353
394
|
this.cancelResizeObserver()
|
|
354
395
|
},
|
|
355
396
|
methods: {
|
|
356
|
-
|
|
357
|
-
|
|
397
|
+
magnifierTap(e,v) {
|
|
398
|
+
if(!v.show) this.extendRightDel()
|
|
399
|
+
v.show = !v.show
|
|
400
|
+
setTimeout(() => {
|
|
401
|
+
const w = e.target.nextSibling.offsetWidth
|
|
402
|
+
const x = (v.rect[0] * this.scales / this.viewport?.width) * 100
|
|
403
|
+
const y = ((this.viewport?.height - (v.rect[1] * this.scales)) / this.viewport?.height) * 100
|
|
404
|
+
if(x > 50) {
|
|
405
|
+
v.style.left = `-${w?w + 5:0}px`
|
|
406
|
+
}else {
|
|
407
|
+
v.style.right = `-${w?w + 5:0}px`
|
|
408
|
+
}
|
|
409
|
+
if(y > 40) {
|
|
410
|
+
v.style.bottom = '0px'
|
|
411
|
+
}else {
|
|
412
|
+
v.style.top = '0px'
|
|
413
|
+
}
|
|
414
|
+
},20)
|
|
415
|
+
},
|
|
416
|
+
extendRightDel() {
|
|
417
|
+
this.rightMenuShow = false
|
|
418
|
+
this.annotations.map(x => {
|
|
419
|
+
x.show = false
|
|
420
|
+
return x
|
|
421
|
+
})
|
|
422
|
+
},
|
|
423
|
+
annotationTap(v, n ) {
|
|
424
|
+
if(v.url) return
|
|
425
|
+
if(n === 'add') {
|
|
426
|
+
this.$emit('annotationsSend', {
|
|
427
|
+
id: v.id,
|
|
428
|
+
page: v.page,
|
|
429
|
+
borderColor: v.borderColor,
|
|
430
|
+
borderStyle: v.borderStyle,
|
|
431
|
+
rect: v.rect,
|
|
432
|
+
})
|
|
433
|
+
}else {
|
|
434
|
+
this.$emit('annotationTap',v)
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
// 扩展点击
|
|
438
|
+
extendRight(i) {
|
|
439
|
+
this.extendRightDel()
|
|
440
|
+
this.$emit('annotationsSend', {
|
|
441
|
+
...this.annData,
|
|
442
|
+
id: new Date().getTime(),
|
|
443
|
+
page: i? i + 1 : this.pageIndex,
|
|
444
|
+
})
|
|
445
|
+
},
|
|
446
|
+
// 右键菜单
|
|
447
|
+
rightMenu(e) {
|
|
448
|
+
e.preventDefault()
|
|
449
|
+
if(this.doublePage) return;
|
|
450
|
+
if(e.target.nodeName === 'SPAN') {
|
|
451
|
+
const wid = this.$refs.wrap.offsetWidth - 10
|
|
452
|
+
const hei = this.$refs.wrap.offsetHeight - 10
|
|
453
|
+
const endOffset = this.getRange().endOffset
|
|
454
|
+
const style = e.target.attributes.style.value
|
|
455
|
+
const size = style.match(/font-size:\s*([^;]+)/)[1].trim().replace(/px/g, "")
|
|
456
|
+
const topMatch = style.match(/top:\s*([^;]+)/)[1].trim().replace(/%/g, "");
|
|
457
|
+
const x1 = this.viewport.width * (e.target.offsetLeft + (endOffset * Number(size)))/wid
|
|
458
|
+
const y1 = this.viewport.height * (1 - (Number(topMatch/100))) - 3
|
|
459
|
+
const x2 = x1 + 15
|
|
460
|
+
const y2 = y1 + 15
|
|
461
|
+
const left = e.target.offsetLeft + e.offsetX
|
|
462
|
+
this.rightMenuShow = true
|
|
463
|
+
this.extendStyle = {
|
|
464
|
+
left: left + 'px',
|
|
465
|
+
top: Number(topMatch) + ((size/hei)*100) + '%'
|
|
466
|
+
}
|
|
467
|
+
this.annData = {
|
|
468
|
+
rect: [x1/this.scales,y1/this.scales,x2/this.scales,y2/this.scales],
|
|
469
|
+
type: 'tag',
|
|
470
|
+
borderStyle: {width: 0},
|
|
471
|
+
borderColor: [0,0,0]
|
|
472
|
+
}
|
|
473
|
+
}
|
|
358
474
|
},
|
|
359
475
|
// 添加标注
|
|
360
476
|
flipText(next) {
|
|
361
|
-
if(this.doublePage) return;
|
|
362
477
|
let timestamp = 'flip' + Math.random().toString(36).substr(2)
|
|
363
478
|
this.replaceSelectedStrByEle(timestamp)
|
|
364
479
|
const elements = document.querySelectorAll(`.${timestamp}`)[0];
|
|
@@ -428,6 +543,7 @@ export default {
|
|
|
428
543
|
return range
|
|
429
544
|
},
|
|
430
545
|
styleAnnotation(v) {
|
|
546
|
+
if(!v) return {}
|
|
431
547
|
const x1 = (v.rect[0] * this.scales / this.viewport?.width) * 100
|
|
432
548
|
const y1 = ((this.viewport?.height - (v.rect[1] * this.scales)) / this.viewport?.height) * 100
|
|
433
549
|
const x2 = (((v.rect[2] - v.rect[0]) * this.scales) / this.viewport?.width) * 100
|
|
@@ -441,6 +557,7 @@ export default {
|
|
|
441
557
|
}
|
|
442
558
|
},
|
|
443
559
|
styleText(v,n, id) {
|
|
560
|
+
if(!v) return {}
|
|
444
561
|
const textLayer = id? this.$refs[`wrap-${id}`][0] : this.$refs.textLayer;
|
|
445
562
|
const actualWidth = textLayer.clientWidth
|
|
446
563
|
const pageScale = actualWidth / this.viewWidth
|
|
@@ -1331,7 +1448,7 @@ export default {
|
|
|
1331
1448
|
cMapPacked: true
|
|
1332
1449
|
})
|
|
1333
1450
|
loadingTask.promise.then((pdf) => {
|
|
1334
|
-
pdfs = pdf
|
|
1451
|
+
pdfs[that.id] = pdf
|
|
1335
1452
|
that.pdfPages = pdf.numPages // 获取pdf文件的总页数
|
|
1336
1453
|
that.$nextTick(() => {
|
|
1337
1454
|
if (that.doublePage) {
|
|
@@ -1356,7 +1473,7 @@ export default {
|
|
|
1356
1473
|
let that = this
|
|
1357
1474
|
that.mouse()
|
|
1358
1475
|
that.$nextTick(() => {
|
|
1359
|
-
pdfs.getPage(that.pageIndex).then(function (page) {
|
|
1476
|
+
pdfs[that.id].getPage(that.pageIndex).then(function (page) {
|
|
1360
1477
|
that.doc = page
|
|
1361
1478
|
that.viewWidth = page.view[2] - page.view[0]
|
|
1362
1479
|
that.viewHeight = page.view[3] - page.view[1]
|
|
@@ -1404,15 +1521,16 @@ export default {
|
|
|
1404
1521
|
that.styles = res.styles
|
|
1405
1522
|
})
|
|
1406
1523
|
page.getAnnotations().then((res) => {
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
}
|
|
1524
|
+
that.annotationsInit = res
|
|
1525
|
+
const arr = that.annotationsData.map(x => {
|
|
1526
|
+
return {
|
|
1527
|
+
...x,
|
|
1528
|
+
show: false,
|
|
1529
|
+
style: {},
|
|
1530
|
+
type: "tag"
|
|
1531
|
+
}
|
|
1532
|
+
})
|
|
1533
|
+
that.annotations = res.concat(arr)
|
|
1416
1534
|
})
|
|
1417
1535
|
that.loading = false
|
|
1418
1536
|
if (that.oneIndex === 'right') {
|
|
@@ -1440,7 +1558,7 @@ export default {
|
|
|
1440
1558
|
that.mouse()
|
|
1441
1559
|
that.$nextTick(() => {
|
|
1442
1560
|
that.pageInfoArr.forEach((item, index) => {
|
|
1443
|
-
pdfs.getPage(index + 1).then(function (page) {
|
|
1561
|
+
pdfs[that.id].getPage(index + 1).then(function (page) {
|
|
1444
1562
|
that.doc = page
|
|
1445
1563
|
that.viewWidth = page.view[2] - page.view[0]
|
|
1446
1564
|
that.viewHeight = page.view[3] - page.view[1]
|
|
@@ -1488,14 +1606,8 @@ export default {
|
|
|
1488
1606
|
item.styles = res.styles
|
|
1489
1607
|
})
|
|
1490
1608
|
page.getAnnotations().then((res) => {
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
setTimeout(() => {
|
|
1494
|
-
that.inits = false
|
|
1495
|
-
},1000)
|
|
1496
|
-
}else {
|
|
1497
|
-
item.annotations = res
|
|
1498
|
-
}
|
|
1609
|
+
that.annotationsInit = res
|
|
1610
|
+
that.annotations = res.concat(that.annotationsData)
|
|
1499
1611
|
})
|
|
1500
1612
|
that.loading = false
|
|
1501
1613
|
if (that.oneIndex === 'right') {
|
|
@@ -1531,6 +1643,67 @@ export default {
|
|
|
1531
1643
|
@import '../icon.css';
|
|
1532
1644
|
@import '../annotationLayer.css';
|
|
1533
1645
|
@import '../textLayer.css';
|
|
1646
|
+
.magnifier{
|
|
1647
|
+
position: absolute;
|
|
1648
|
+
text-align: initial;
|
|
1649
|
+
pointer-events: auto;
|
|
1650
|
+
box-sizing: border-box;
|
|
1651
|
+
transform-origin: 0 0;
|
|
1652
|
+
cursor: pointer;
|
|
1653
|
+
}
|
|
1654
|
+
.magnifier>img{
|
|
1655
|
+
width: 100%;
|
|
1656
|
+
height: 100%;
|
|
1657
|
+
display: block;
|
|
1658
|
+
}
|
|
1659
|
+
.magnifier-list{
|
|
1660
|
+
position: absolute;
|
|
1661
|
+
max-width: 300px;
|
|
1662
|
+
background-color: #fff;
|
|
1663
|
+
border-radius: 5px;
|
|
1664
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
|
|
1665
|
+
padding: 10px 20px;
|
|
1666
|
+
font-size: 14px;
|
|
1667
|
+
z-index: 1;
|
|
1668
|
+
animation: linkDown .4s linear forwards;
|
|
1669
|
+
opacity: 0;
|
|
1670
|
+
}
|
|
1671
|
+
.magnifier-list-item{
|
|
1672
|
+
line-height: 24px;
|
|
1673
|
+
overflow: hidden;
|
|
1674
|
+
text-overflow: ellipsis;
|
|
1675
|
+
white-space: nowrap;
|
|
1676
|
+
}
|
|
1677
|
+
.magnifier-list-item:hover{
|
|
1678
|
+
color: #4B0C77 !important;
|
|
1679
|
+
}
|
|
1680
|
+
@keyframes linkDown {
|
|
1681
|
+
0% {
|
|
1682
|
+
opacity: 0;
|
|
1683
|
+
}
|
|
1684
|
+
50% {
|
|
1685
|
+
opacity: 0;
|
|
1686
|
+
}
|
|
1687
|
+
100% {
|
|
1688
|
+
opacity: 1;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
.magnifier-list-add{
|
|
1692
|
+
color: #666;
|
|
1693
|
+
font-size: 12px;
|
|
1694
|
+
padding: 5px 0;
|
|
1695
|
+
}
|
|
1696
|
+
.extend-right{
|
|
1697
|
+
position: absolute;
|
|
1698
|
+
z-index: 5;
|
|
1699
|
+
background-color: #fff;
|
|
1700
|
+
border-radius: 5px;
|
|
1701
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
|
|
1702
|
+
padding: 10px 20px;
|
|
1703
|
+
}
|
|
1704
|
+
.extend-right>p{
|
|
1705
|
+
cursor: pointer;
|
|
1706
|
+
}
|
|
1534
1707
|
.isPointer{
|
|
1535
1708
|
pointer-events: none;
|
|
1536
1709
|
}
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
<script>
|
|
7
7
|
import {createElement} from 'react'
|
|
8
8
|
import {createRoot} from 'react-dom/client'
|
|
9
|
-
import {AssetRecordType,createShapeId, Tldraw
|
|
9
|
+
import {AssetRecordType,createShapeId, Tldraw} from 'tldraw'
|
|
10
10
|
import 'tldraw/tldraw.css'
|
|
11
|
-
import * as buffer from "buffer";
|
|
11
|
+
import * as buffer from "buffer";
|
|
12
|
+
import {debounce} from "../../utils"; //引入buffer
|
|
12
13
|
|
|
13
14
|
if (typeof window.Buffer === "undefined") { // 判断当前环境是否有Buffer对象
|
|
14
15
|
window.Buffer = buffer.Buffer; // Buffer对象不存在则创建导入的buffer
|
|
@@ -153,7 +154,14 @@ export default {
|
|
|
153
154
|
},
|
|
154
155
|
handleMountedEditor(editor) {
|
|
155
156
|
editorAPP = editor
|
|
156
|
-
|
|
157
|
+
editorAPP.sideEffects.registerAfterChangeHandler('shape', debounce((next)=> {
|
|
158
|
+
// there can only be one red shape at a time:
|
|
159
|
+
this.$emit('shapeChangeHandler', next);
|
|
160
|
+
},300))
|
|
161
|
+
editorAPP.sideEffects.registerAfterDeleteHandler('shape', (shape) => {
|
|
162
|
+
// if the last shape in a frame is deleted, delete the frame too:
|
|
163
|
+
this.$emit('shapeDeleteHandler', shape);
|
|
164
|
+
})
|
|
157
165
|
editorAPP.setCameraOptions({ isLocked: this.cameraIsLocked })
|
|
158
166
|
editorAPP.updateInstanceState({ isToolLocked: this.isToolLocked })
|
|
159
167
|
if (this.top) {
|
|
@@ -174,12 +182,13 @@ export default {
|
|
|
174
182
|
// 清空
|
|
175
183
|
clear() {
|
|
176
184
|
// editorAPP.store.loadSnapshot(clearJson)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
185
|
+
editorAPP.selectAll()
|
|
186
|
+
let graphicIds = editorAPP.getSelectedShapeIds()
|
|
187
|
+
// for(let key in editorAPP.store.query.atoms.current) {
|
|
188
|
+
// if(key.split(':')[0]==='shape') {
|
|
189
|
+
// graphicIds.push(key)
|
|
190
|
+
// }
|
|
191
|
+
// }
|
|
183
192
|
editorAPP.deleteShapes(graphicIds)
|
|
184
193
|
},
|
|
185
194
|
// 添加快照
|
|
@@ -10,4 +10,16 @@ export function debounce(fn, delay = debounceTimer) {
|
|
|
10
10
|
fn.apply(that, args)
|
|
11
11
|
}, delay)
|
|
12
12
|
}
|
|
13
|
+
}
|
|
14
|
+
export function throttle(fn, limit=debounceTimer) {
|
|
15
|
+
let inThrottle;
|
|
16
|
+
return function() {
|
|
17
|
+
const args = arguments;
|
|
18
|
+
const context = this;
|
|
19
|
+
if (!inThrottle) {
|
|
20
|
+
fn.apply(context, args);
|
|
21
|
+
inThrottle = true;
|
|
22
|
+
setTimeout(() => { inThrottle = false; }, limit);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
13
25
|
}
|