zhuhao_dev #109
|
@ -0,0 +1,35 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 新增pdf圈点勾画
|
||||||
|
export const addsmartBookMark = (params) => {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/bookMark/addSmartBookMark',
|
||||||
|
method: 'post',
|
||||||
|
data:params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改pdf圈点勾画
|
||||||
|
export const updateSmartBookMarkContent = (params) => {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/bookMark/updateSmartBookMarkContent',
|
||||||
|
method: 'post',
|
||||||
|
data:params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据书id获取pdf圈点勾画
|
||||||
|
export const getBookMarkById = (bookId) => {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/bookMark/' + bookId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据id删除对应页数
|
||||||
|
export function deleteBookMark(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/bookMark/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 2794390 */
|
font-family: "iconfont"; /* Project id 2794390 */
|
||||||
src: url('iconfont.woff2?t=1722393125520') format('woff2'),
|
src: url('iconfont.woff2?t=1723022855912') format('woff2'),
|
||||||
url('iconfont.woff?t=1722393125520') format('woff'),
|
url('iconfont.woff?t=1723022855912') format('woff'),
|
||||||
url('iconfont.ttf?t=1722393125520') format('truetype'),
|
url('iconfont.ttf?t=1723022855912') format('truetype'),
|
||||||
url('iconfont.svg?t=1722393125520#iconfont') format('svg');
|
url('iconfont.svg?t=1723022855912#iconfont') format('svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
@ -14,6 +14,26 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-kechengziyuan1:before {
|
||||||
|
content: "\e647";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-tubiaozhizuomobanyihuifu-:before {
|
||||||
|
content: "\e69d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-window-01:before {
|
||||||
|
content: "\e70b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-chuangkou-chuangkouhua:before {
|
||||||
|
content: "\e64b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-a-lujing13357:before {
|
||||||
|
content: "\e64c";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-icon:before {
|
.icon-icon:before {
|
||||||
content: "\e640";
|
content: "\e640";
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,41 @@
|
||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "3053509",
|
||||||
|
"name": "课程资源",
|
||||||
|
"font_class": "kechengziyuan1",
|
||||||
|
"unicode": "e647",
|
||||||
|
"unicode_decimal": 58951
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4427402",
|
||||||
|
"name": "窗口",
|
||||||
|
"font_class": "tubiaozhizuomobanyihuifu-",
|
||||||
|
"unicode": "e69d",
|
||||||
|
"unicode_decimal": 59037
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "18418603",
|
||||||
|
"name": "窗口",
|
||||||
|
"font_class": "window-01",
|
||||||
|
"unicode": "e70b",
|
||||||
|
"unicode_decimal": 59147
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "30970631",
|
||||||
|
"name": "窗口-窗口化",
|
||||||
|
"font_class": "chuangkou-chuangkouhua",
|
||||||
|
"unicode": "e64b",
|
||||||
|
"unicode_decimal": 58955
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "41196567",
|
||||||
|
"name": "下课",
|
||||||
|
"font_class": "a-lujing13357",
|
||||||
|
"unicode": "e64c",
|
||||||
|
"unicode_decimal": 58956
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "680440",
|
"icon_id": "680440",
|
||||||
"name": "教材",
|
"name": "教材",
|
||||||
|
|
|
@ -14,6 +14,16 @@
|
||||||
/>
|
/>
|
||||||
<missing-glyph />
|
<missing-glyph />
|
||||||
|
|
||||||
|
<glyph glyph-name="kechengziyuan1" unicode="" d="M530.299631 315.712191a54.537462 54.537462 0 0 0-34.299976 12.187492L19.862486 563.299519l-3.749997 3.749997a55.187462 55.187462 0 0 0 0 77.949946l3.749997 3.749998L495.687155 883.836796A54.537462 54.537462 0 0 0 530.299631 895.999288a54.562462 54.562462 0 0 0 34.299976-12.162492l476.137169-235.424836 3.749997-3.749998a55.199962 55.199962 0 0 0 0-77.949945l-3.749997-3.749998-476.137169-235.399836a54.562462 54.562462 0 0 0-34.299976-11.849992z m-455.874683 289.999798l455.874683-225.449843 455.874683 225.437343-455.874683 225.749843z m0 0M530.299631 94.012346a54.574962 54.574962 0 0 0-34.299976 12.162491L24.537483 339.149675a31.174978 31.174978 0 1 0 27.749981 55.812461l474.899669-234.849836 3.112498-1.874999 3.124998 1.874999 474.887169 235.112336a31.174978 31.174978 0 0 0 27.749981-55.812461L564.599607 105.862337a54.562462 54.562462 0 0 0-34.299976-11.849991z m0 0M530.299631-128a54.862462 54.862462 0 0 0-34.299976 12.149992L24.537483 116.46233a31.174978 31.174978 0 1 0 27.749981 55.812461l474.899669-233.862337 3.112498-1.874999 3.124998 1.874999 474.887169 235.112336a31.724978 31.724978 0 1 0 27.749981-57.06246L564.599607-115.850008a55.199962 55.199962 0 0 0-34.299976-12.149992z m0 0" horiz-adv-x="1060" />
|
||||||
|
|
||||||
|
<glyph glyph-name="tubiaozhizuomobanyihuifu-" unicode="" d="M695.48 353.85m-15 0a15 15 0 1 1 30 0 15 15 0 1 1-30 0ZM586.39 17.63A28.63 28.63 0 0 0 557.76-11H122.39V424.37A28.63 28.63 0 0 0 151 453h156.39v79H152A108.63 108.63 0 0 1 43.39 423.37V-91h514.37a108.63 108.63 0 0 1 108.63 108.63V174h-80zM359.39 749v-523h523a100 100 0 0 1 100 100V849h-523a100 100 0 0 1-100-100z m523-443h-443V749a20 20 0 0 0 20 20h443v-443a20 20 0 0 0-20-20zM751.9 339h102a15.5 15.5 0 0 1 15.5 15.5V581.9a5.25 5.25 0 0 1-1.54 3.75c-13 12.72-28.46 3.75-28.46-8.84v-202.64a5.17 5.17 0 0 0-5.17-5.17H746.8a5.25 5.25 0 0 1-3.75-1.54c-12.71-12.95-3.74-28.46 8.85-28.46z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
<glyph glyph-name="window-01" unicode="" d="M176 664c0 30.93 25.07 56 56 56h616v56c0 30.93-25.07 56-56 56H120c-30.93 0-56-25.07-56-56v-672c0-30.93 25.07-56 56-56h56V664zM176-8V664c0 30.93 25.07 56 56 56h672c30.93 0 56-25.07 56-56v-672c0-30.93-25.07-56-56-56H232c-30.93 0-56 25.07-56 56zM960 548.5H176V664c0 30.93 25.07 56 56 56h672c30.93 0 56-25.07 56-56v-115.5zM274 634.25m-24.5 0a24.5 24.5 0 1 1 49 0 24.5 24.5 0 1 1-49 0ZM347.5 634.25m-24.5 0a24.5 24.5 0 1 1 49 0 24.5 24.5 0 1 1-49 0ZM421 634.25m-24.5 0a24.5 24.5 0 1 1 49 0 24.5 24.5 0 1 1-49 0ZM629.25 381.08h-269.5c-20.3 0-36.75-16.45-36.75-36.75s16.45-36.75 36.75-36.75h269.5c20.3 0 36.75 16.45 36.75 36.75s-16.45 36.75-36.75 36.75zM776.25 176.92h-416.5c-20.3 0-36.75-16.45-36.75-36.75s16.45-36.75 36.75-36.75h416.5c20.3 0 36.75 16.45 36.75 36.75 0 20.29-16.45 36.75-36.75 36.75z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
<glyph glyph-name="chuangkou-chuangkouhua" unicode="" d="M877.714286 164.571429h-146.285715v-146.285715c0-80.790674-65.49504-146.285714-146.285714-146.285714H146.285714c-80.790674 0-146.285714 65.49504-146.285714 146.285714V457.142857c0 80.790674 65.49504 146.285714 146.285714 146.285714h146.285715V749.714286C292.571429 830.50496 358.066469 896 438.857143 896h438.857143c80.790674 0 146.285714-65.49504 146.285714-146.285714v-438.857143c0-80.790674-65.49504-146.285714-146.285714-146.285714zM146.285714 530.285714c-40.398263 0-73.142857-32.744594-73.142857-73.142857v-438.857143c0-40.398263 32.744594-73.142857 73.142857-73.142857h438.857143c40.398263 0 73.142857 32.744594 73.142857 73.142857V457.142857c0 40.398263-32.744594 73.142857-73.142857 73.142857H146.285714zM950.857143 749.714286c0 40.398263-32.744594 73.142857-73.142857 73.142857H438.857143c-40.398263 0-73.142857-32.744594-73.142857-73.142857v-146.285715H585.142857c80.790674 0 146.285714-65.49504 146.285714-146.285714v-219.428571h146.285715c40.398263 0 73.142857 32.744594 73.142857 73.142857V749.714286z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
<glyph glyph-name="a-lujing13357" unicode="" d="M826.923942 449.891603c0 160.392197-86.723391 296.927783-236.108782 330.664923v36.552834a78.89064 78.89064 0 0 1-157.781281 0v-36.808807c-149.385392-36.552834-236.108782-170.835864-236.108782-330.664922v-262.781089L91.92529 81.854735v-52.781473h839.99846v53.037445l-104.999808 104.999808zM511.92452-127.888908a57.491362 57.491362 0 0 1 20.887333 2.610917 105.25578 105.25578 0 0 1 84.112474 104.999807h-209.897226A105.921308 105.921308 0 0 1 511.92452-127.888908zM94.024262 466.580992a25.597223 25.597223 0 0 0-6.245722 0.511944 40.955556 40.955556 0 0 0-35.017001 47.55964A596.77365 596.77365 0 0 0 227.744153 855.761166 41.723473 41.723473 0 1 0 285.696265 795.658887a514.504176 514.504176 0 0 1-150.460475-293.600144 42.03064 42.03064 0 0 0-41.211528-35.477751z m835.85171 0a25.597223 25.597223 0 0 1 6.245722 0.511944 40.955556 40.955556 0 0 1 35.017001 47.55964A596.77365 596.77365 0 0 1 796.156081 855.761166a41.774667 41.774667 0 1 1-58.054501-60.102279 514.504176 514.504176 0 0 0 150.460475-293.600144 42.03064 42.03064 0 0 1 41.262723-35.528945z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
<glyph glyph-name="icon" unicode="" d="M817.068044 743.163079 804.40463 743.163079l0 0.814552c0 54.475705-44.572148 99.047854-99.047854 99.047854L206.750831 843.025485c-54.4491 0-98.998735-44.550659-98.998735-98.999758l0-608.958262c0-54.475705 44.570101-99.045807 99.045807-99.045807l12.664438 0 0-0.815575c0-54.475705 44.570101-99.045807 99.045807-99.045807l498.559896 0c54.475705 0 99.047854 44.570101 99.047854 99.045807L916.115897 644.116249C916.115897 698.591955 871.543749 743.163079 817.068044 743.163079zM148.374282 157.929148 148.374282 721.158926c0 44.683688 36.559661 81.244372 81.244372 81.244372l452.878484 0c44.707225 0 81.286328-36.579103 81.286328-81.287351l0-563.185776c0-44.708248-36.579103-81.286328-81.286328-81.286328L229.66061 76.643843C184.952362 76.64282 148.374282 113.2209 148.374282 157.929148zM875.493711 58.067766c0-44.708248-36.579103-81.286328-81.286328-81.286328L341.370855-23.218562c-37.036521 0-68.249407 25.203008-77.943187 59.240219l441.929108 0c54.475705 0 99.047854 44.570101 99.047854 99.045807L804.40463 701.456189c39.885406-5.097088 71.089082-38.987966 71.089082-80.202647L875.493711 58.067766zM392.899438 313.767426c0-5.712095-2.856048-8.568143-8.569166-8.568143l-71.406307 0 0-38.560224 89.971128 0c25.706475 0 38.559201 14.772448 38.559201 44.272319l0 22.849404 21.421892 0 0 41.416272-19.99438 0 11.425214 21.421892 0 44.271296-84.259032 0 4.284583 15.709797 88.543615 0 0 41.415248-55.69651 0 0 34.275641 55.69651 0 0 39.987736-55.69651 0 0 21.421892-48.555879 0 0-19.993357-61.409628 0 0-41.415248 61.409628 0 0-34.275641-61.409628 0 0-41.415248 22.850427 0-4.284583-14.281261c-3.815909-4.77577-7.631818-7.140631-11.425214-7.140631l-7.140631 0 0-44.272319 34.274618 0c11.425214 0 20.463054 2.856048 27.13501 8.569166l42.843784 0-12.853749-24.27794-91.399663 0 0-41.416272 95.684246 0L392.898415 313.767426zM525.71435 503.707382l5.713119 24.27794 98.540294 0 0 39.987736-89.972151 0 5.712095 21.421892-48.555879 0-12.853749-49.984415c-1.918699-6.671956-5.712095-9.529027-11.425214-8.569166l-5.713119 0 0-41.416272 32.847106 0C512.370437 489.426121 520.939603 494.179378 525.71435 503.707382zM537.139563 275.208225l11.425214 22.849404 12.852726-21.421892c6.650467-12.362562 15.21861-18.565844 25.706475-18.565844l44.272319 0 0 38.559201-14.281261 0c-6.67298-0.959861-11.916401 3.793396-15.709797 14.281261l-24.278963 55.697533 47.128367 132.814911-58.552557 0-19.99438-65.694211-18.565844 42.843784-57.125045 0 48.556902-111.394043-19.99438-57.124022c-3.815909-8.569166-9.060353-12.853749-15.709797-12.853749l-17.137309 0 0-37.130665 47.128367 0C524.286838 259.030777 532.363793 264.742872 537.139563 275.208225z" horiz-adv-x="1024" />
|
<glyph glyph-name="icon" unicode="" d="M817.068044 743.163079 804.40463 743.163079l0 0.814552c0 54.475705-44.572148 99.047854-99.047854 99.047854L206.750831 843.025485c-54.4491 0-98.998735-44.550659-98.998735-98.999758l0-608.958262c0-54.475705 44.570101-99.045807 99.045807-99.045807l12.664438 0 0-0.815575c0-54.475705 44.570101-99.045807 99.045807-99.045807l498.559896 0c54.475705 0 99.047854 44.570101 99.047854 99.045807L916.115897 644.116249C916.115897 698.591955 871.543749 743.163079 817.068044 743.163079zM148.374282 157.929148 148.374282 721.158926c0 44.683688 36.559661 81.244372 81.244372 81.244372l452.878484 0c44.707225 0 81.286328-36.579103 81.286328-81.287351l0-563.185776c0-44.708248-36.579103-81.286328-81.286328-81.286328L229.66061 76.643843C184.952362 76.64282 148.374282 113.2209 148.374282 157.929148zM875.493711 58.067766c0-44.708248-36.579103-81.286328-81.286328-81.286328L341.370855-23.218562c-37.036521 0-68.249407 25.203008-77.943187 59.240219l441.929108 0c54.475705 0 99.047854 44.570101 99.047854 99.045807L804.40463 701.456189c39.885406-5.097088 71.089082-38.987966 71.089082-80.202647L875.493711 58.067766zM392.899438 313.767426c0-5.712095-2.856048-8.568143-8.569166-8.568143l-71.406307 0 0-38.560224 89.971128 0c25.706475 0 38.559201 14.772448 38.559201 44.272319l0 22.849404 21.421892 0 0 41.416272-19.99438 0 11.425214 21.421892 0 44.271296-84.259032 0 4.284583 15.709797 88.543615 0 0 41.415248-55.69651 0 0 34.275641 55.69651 0 0 39.987736-55.69651 0 0 21.421892-48.555879 0 0-19.993357-61.409628 0 0-41.415248 61.409628 0 0-34.275641-61.409628 0 0-41.415248 22.850427 0-4.284583-14.281261c-3.815909-4.77577-7.631818-7.140631-11.425214-7.140631l-7.140631 0 0-44.272319 34.274618 0c11.425214 0 20.463054 2.856048 27.13501 8.569166l42.843784 0-12.853749-24.27794-91.399663 0 0-41.416272 95.684246 0L392.898415 313.767426zM525.71435 503.707382l5.713119 24.27794 98.540294 0 0 39.987736-89.972151 0 5.712095 21.421892-48.555879 0-12.853749-49.984415c-1.918699-6.671956-5.712095-9.529027-11.425214-8.569166l-5.713119 0 0-41.416272 32.847106 0C512.370437 489.426121 520.939603 494.179378 525.71435 503.707382zM537.139563 275.208225l11.425214 22.849404 12.852726-21.421892c6.650467-12.362562 15.21861-18.565844 25.706475-18.565844l44.272319 0 0 38.559201-14.281261 0c-6.67298-0.959861-11.916401 3.793396-15.709797 14.281261l-24.278963 55.697533 47.128367 132.814911-58.552557 0-19.99438-65.694211-18.565844 42.843784-57.125045 0 48.556902-111.394043-19.99438-57.124022c-3.815909-8.569166-9.060353-12.853749-15.709797-12.853749l-17.137309 0 0-37.130665 47.128367 0C524.286838 259.030777 532.363793 264.742872 537.139563 275.208225z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
<glyph glyph-name="ke" unicode="" d="M898.357594 896H133.939604C62.429691 896 4.14672 837.712018 4.14672 766.205864v-764.416738c0-71.504902 58.282971-129.787873 129.792884-129.787873h764.41799c71.504902 0 129.787873 58.282971 129.787873 129.787873V766.205864C1028.145467 837.712018 969.862496 896 898.357594 896z m61.306917-150.971773v-722.056454c0-45.545824-37.100324-82.489564-82.494575-82.489564H155.278835c-45.545824 0-82.494575 37.100324-82.494574 82.489564V744.866632c0 45.547077 37.110345 82.495827 82.494574 82.495828H877.169936c45.394251 0.161594 82.494575-36.787156 82.494575-82.334233z m0 0M219.605939 497.65098h140.299026v-256.17099c16.695584 15.442914 31.943082 30.269515 45.72245 44.469781l15.658373-60.754489c-33.411211-33.411211-70.775848-64.512499-112.113953-93.323906l-22.548058 52.612135c10.432235 9.179565 15.658373 19.621821 15.658373 31.316747V440.6545H219.605939V497.65098z m85.181551 181.637132c40.085436-30.484974 73.907523-61.175386 101.46626-92.071236l-40.711771-41.338106c-25.053398 29.64318-59.296381 60.53903-102.71893 92.697571L304.78749 679.288112z m134.662012-16.911044H759.506655V412.469428H626.723648v-47.601455h160.341744v-55.117475h-112.113954c26.306067-49.275022 69.307719-93.744803 129.024997-133.409341l-38.206431-47.601455c-64.307061 54.696577-109.824073 115.030169-136.541016 181.010796h-2.50534v-202.306184h-55.74381V309.750498H569.100834c-30.064077-73.496647-78.291867-134.035677-144.683371-181.637131L393.727051 178.846497c58.03369 35.485632 101.250801 79.12364 129.651332 130.904001h-110.234949v55.117475h157.836404v47.601455h-131.530336V662.377068zM493.940641 560.2844729999999h77.039197v50.73313H493.940641V560.2844729999999z m77.039197-97.70825v49.48046H493.940641V462.576223h77.039197zM626.723648 611.017603V560.2844729999999h78.291867v50.73313H626.723648zM705.015515 462.576223v49.48046H626.723648V462.576223h78.291867z" horiz-adv-x="1056" />
|
<glyph glyph-name="ke" unicode="" d="M898.357594 896H133.939604C62.429691 896 4.14672 837.712018 4.14672 766.205864v-764.416738c0-71.504902 58.282971-129.787873 129.792884-129.787873h764.41799c71.504902 0 129.787873 58.282971 129.787873 129.787873V766.205864C1028.145467 837.712018 969.862496 896 898.357594 896z m61.306917-150.971773v-722.056454c0-45.545824-37.100324-82.489564-82.494575-82.489564H155.278835c-45.545824 0-82.494575 37.100324-82.494574 82.489564V744.866632c0 45.547077 37.110345 82.495827 82.494574 82.495828H877.169936c45.394251 0.161594 82.494575-36.787156 82.494575-82.334233z m0 0M219.605939 497.65098h140.299026v-256.17099c16.695584 15.442914 31.943082 30.269515 45.72245 44.469781l15.658373-60.754489c-33.411211-33.411211-70.775848-64.512499-112.113953-93.323906l-22.548058 52.612135c10.432235 9.179565 15.658373 19.621821 15.658373 31.316747V440.6545H219.605939V497.65098z m85.181551 181.637132c40.085436-30.484974 73.907523-61.175386 101.46626-92.071236l-40.711771-41.338106c-25.053398 29.64318-59.296381 60.53903-102.71893 92.697571L304.78749 679.288112z m134.662012-16.911044H759.506655V412.469428H626.723648v-47.601455h160.341744v-55.117475h-112.113954c26.306067-49.275022 69.307719-93.744803 129.024997-133.409341l-38.206431-47.601455c-64.307061 54.696577-109.824073 115.030169-136.541016 181.010796h-2.50534v-202.306184h-55.74381V309.750498H569.100834c-30.064077-73.496647-78.291867-134.035677-144.683371-181.637131L393.727051 178.846497c58.03369 35.485632 101.250801 79.12364 129.651332 130.904001h-110.234949v55.117475h157.836404v47.601455h-131.530336V662.377068zM493.940641 560.2844729999999h77.039197v50.73313H493.940641V560.2844729999999z m77.039197-97.70825v49.48046H493.940641V462.576223h77.039197zM626.723648 611.017603V560.2844729999999h78.291867v50.73313H626.723648zM705.015515 462.576223v49.48046H626.723648V462.576223h78.291867z" horiz-adv-x="1056" />
|
||||||
|
|
Before Width: | Height: | Size: 261 KiB After Width: | Height: | Size: 261 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,217 @@
|
||||||
|
<template>
|
||||||
|
<div class="canvasitem">
|
||||||
|
<div class="pdfAdnFabric" id="pdfAdnFabric">
|
||||||
|
<canvas id="pdf-fabric"></canvas>
|
||||||
|
<canvas id="pdf-fabric1" v-if="props.pdfObj.numberOfPdf == 2"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup >
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
watch,
|
||||||
|
reactive,
|
||||||
|
nextTick,
|
||||||
|
} from 'vue'
|
||||||
|
import { fabric } from 'fabric'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { handleevent, savecanvsStore, initcanvasdata, displayData } from '@/utils/pdfAndFabric'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
pdfObj: {
|
||||||
|
type: Object,
|
||||||
|
default: {
|
||||||
|
numberOfPdf: 2, //pdf数量 只有 1 2
|
||||||
|
pdfUrl: null,
|
||||||
|
numPages: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// canvas的所有数据
|
||||||
|
const canvsStore = reactive({
|
||||||
|
id: 'xxxx',
|
||||||
|
pageArr: []
|
||||||
|
})
|
||||||
|
const fabriccanvas = ref(null)
|
||||||
|
const fabriccanvas1 = ref(null)
|
||||||
|
// 页面总数
|
||||||
|
const numPagesTotal = ref(0)
|
||||||
|
const imgarr = ref([])
|
||||||
|
// 多个pdf的对象
|
||||||
|
const canvasNumbsValue = ref([])
|
||||||
|
const emit = defineEmits(['update:numPagesTotal'])
|
||||||
|
const renderPage = async (canvasobj) => {
|
||||||
|
if (canvasobj.page > numPagesTotal.value) return
|
||||||
|
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
||||||
|
// 渲染当前页
|
||||||
|
const page = await pdf.getPage(canvasobj.page)
|
||||||
|
var screenWidth = window.innerWidth/2-100;
|
||||||
|
var screenHeight = window.innerHeight;
|
||||||
|
const viewport = page.getViewport({ scale:2})
|
||||||
|
|
||||||
|
const canvasElement = canvasobj.canvas
|
||||||
|
canvasElement.width = viewport.width
|
||||||
|
canvasElement.height = viewport.height
|
||||||
|
const renderContext = {
|
||||||
|
canvasContext: canvasobj.context,
|
||||||
|
viewport: viewport
|
||||||
|
}
|
||||||
|
page.render(renderContext).promise.then((res) => {
|
||||||
|
const img = document.createElement('img')
|
||||||
|
img.src = canvasobj.canvas.toDataURL('image/png')
|
||||||
|
canvasobj.canvas.remove()
|
||||||
|
imgarr.value.push({ src: img.src, page: canvasobj.page, JSONdata: {}, index: canvasobj.index })
|
||||||
|
img.onload = () => {
|
||||||
|
// 在这里执行图像加载完成后的操作
|
||||||
|
// 根据传过来的pdf对象 判断改渲染哪一个fabric
|
||||||
|
if (props.pdfObj.numberOfPdf == 2) {
|
||||||
|
if (canvasobj.index == 0) {
|
||||||
|
|
||||||
|
fabriccanvas.value.setWidth(screenWidth)
|
||||||
|
fabriccanvas.value.setHeight(screenHeight)
|
||||||
|
displayData(fabriccanvas, canvsStore, canvasobj, fabric, img)
|
||||||
|
} else {
|
||||||
|
fabriccanvas1.value.setWidth(screenWidth)
|
||||||
|
fabriccanvas1.value.setHeight(screenHeight)
|
||||||
|
displayData(fabriccanvas1, canvsStore, canvasobj, fabric, img)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fabriccanvas.value.setWidth(screenWidth)
|
||||||
|
fabriccanvas.value.setHeight(screenHeight)
|
||||||
|
displayData(fabriccanvas, canvsStore, canvasobj, fabric, img)
|
||||||
|
}
|
||||||
|
// console.log(imgarr.value)
|
||||||
|
img.remove()
|
||||||
|
}
|
||||||
|
// 判断imgarr的JSONdata在canvsStore.pageArr有没有
|
||||||
|
canvsStore.pageArr.forEach((item) => {
|
||||||
|
if (item.page == canvasobj.page) {
|
||||||
|
imgarr.value.forEach((img) => {
|
||||||
|
if (img.page == canvasobj.page) {
|
||||||
|
img.JSONdata = item.JSONdata
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const updatePage = (canvasobj) => {
|
||||||
|
renderPage(canvasobj)
|
||||||
|
}
|
||||||
|
const loadPdf = async (canvasobj) => {
|
||||||
|
updatePage(canvasobj)
|
||||||
|
}
|
||||||
|
|
||||||
|
const initPdf = async (type = 'default') => {
|
||||||
|
// 保存数据
|
||||||
|
savecanvsStore(imgarr, canvsStore)
|
||||||
|
// initcanvasdata(fabriccanvas)
|
||||||
|
// initcanvasdata(fabriccanvas1)
|
||||||
|
// 单页模式
|
||||||
|
if (type == 'restone') {
|
||||||
|
// 清除 canvas 上的所有对象
|
||||||
|
fabriccanvas1.value.clear()
|
||||||
|
// 释放 canvas 的资源
|
||||||
|
fabriccanvas1.value.dispose()
|
||||||
|
}
|
||||||
|
// 清除现有 canvas 元素的内容
|
||||||
|
canvasNumbsValue.value.forEach((canvasObj) => {
|
||||||
|
const context = canvasObj.context
|
||||||
|
context.clearRect(0, 0, canvasObj.canvas.width, canvasObj.canvas.height)
|
||||||
|
})
|
||||||
|
// 清除所有对象
|
||||||
|
imgarr.value = []
|
||||||
|
canvasNumbsValue.value = []
|
||||||
|
if (props.pdfObj.pdfUrl) {
|
||||||
|
await nextTick() // 确保 DOM 渲染完成
|
||||||
|
if (props.pdfObj.numberOfPdf == 1) {
|
||||||
|
canvasNumbsValue.value = [{}]
|
||||||
|
const canvasElement = document.createElement('canvas')
|
||||||
|
canvasNumbsValue.value[0].canvas = canvasElement
|
||||||
|
canvasNumbsValue.value[0].context = canvasNumbsValue.value[0].canvas.getContext('2d')
|
||||||
|
canvasNumbsValue.value[0].page = props.pdfObj.numPages
|
||||||
|
canvasNumbsValue.value[0].index = 0
|
||||||
|
await loadPdf(canvasNumbsValue.value[0])
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < props.pdfObj.numberOfPdf; i++) {
|
||||||
|
canvasNumbsValue.value[i] = {}
|
||||||
|
const canvasElement = document.createElement('canvas')
|
||||||
|
canvasNumbsValue.value[i].canvas = canvasElement
|
||||||
|
canvasNumbsValue.value[i].context = canvasNumbsValue.value[i].canvas.getContext('2d')
|
||||||
|
// 设置页数
|
||||||
|
if (i == 0) {
|
||||||
|
canvasNumbsValue.value[i].page = props.pdfObj.numPages
|
||||||
|
} else {
|
||||||
|
canvasNumbsValue.value[i].page = props.pdfObj.numPages + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
canvasNumbsValue.value[i].index = i
|
||||||
|
// 加载FabricVue
|
||||||
|
await loadPdf(canvasNumbsValue.value[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const initPdfone = async () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
fabriccanvas1.value = new fabric.Canvas('pdf-fabric1')
|
||||||
|
fabriccanvas1.value.isDrawingMode = true
|
||||||
|
fabriccanvas1.value.freeDrawingBrush.color = '#A33AFE'
|
||||||
|
fabriccanvas1.value.freeDrawingCursor = 'default'
|
||||||
|
fabriccanvas1.value.setWidth(860)
|
||||||
|
handleevent(fabriccanvas1.value, imgarr, 'two')
|
||||||
|
}, 0)
|
||||||
|
initPdf('addOnePage')
|
||||||
|
}
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
||||||
|
numPagesTotal.value = pdf.numPages
|
||||||
|
// console.log(pdf)
|
||||||
|
// 初始化fabriccanvas
|
||||||
|
fabriccanvas.value = new fabric.Canvas('pdf-fabric')
|
||||||
|
fabriccanvas.value.setWidth(860)
|
||||||
|
fabriccanvas.value.isDrawingMode = true
|
||||||
|
fabriccanvas.value.freeDrawingBrush.color = '#A33AFE'
|
||||||
|
fabriccanvas.value.freeDrawingCursor = 'default'
|
||||||
|
|
||||||
|
fabriccanvas1.value = new fabric.Canvas('pdf-fabric1')
|
||||||
|
fabriccanvas1.value.isDrawingMode = true
|
||||||
|
fabriccanvas1.value.freeDrawingBrush.color = '#A33AFE'
|
||||||
|
fabriccanvas1.value.freeDrawingCursor = 'default'
|
||||||
|
fabriccanvas1.value.setWidth(860)
|
||||||
|
emit('update:numPagesTotal', pdf.numPages)
|
||||||
|
initPdf()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
ElMessage.error('pdf文件错误')
|
||||||
|
}
|
||||||
|
// 监听2个canvas事件
|
||||||
|
handleevent(fabriccanvas.value, imgarr)
|
||||||
|
handleevent(fabriccanvas1.value, imgarr, 'two')
|
||||||
|
})
|
||||||
|
defineExpose({
|
||||||
|
initPdf,
|
||||||
|
initPdfone
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.canvasitem {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.pdfAdnFabric {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
align-items: center;
|
||||||
|
:deep(> div:nth-of-type(1)) {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,8 +1,18 @@
|
||||||
<template>
|
pdfAdnFabric<template>
|
||||||
<div class="canvasitem">
|
<div class="canvasitem">
|
||||||
<div class="pdfAdnFabric" id="pdfAdnFabric">
|
<div class="pdfAdnFabric" id="pdfAdnFabric" >
|
||||||
<canvas id="pdf-fabric"></canvas>
|
<!-- @touchmove="handleTouchMove"
|
||||||
<canvas id="pdf-fabric1" v-if="props.pdfObj.numberOfPdf == 2"></canvas>
|
@touchend="handleTouchEnd"
|
||||||
|
@mousedown="handleMouseDown"
|
||||||
|
@mousemove="handleMouseMove"
|
||||||
|
@mouseup="handleMouseUp" -->
|
||||||
|
<div :class="ispointer ? 'ispointer' : ''">
|
||||||
|
<canvas ref="fabriccanvas" />
|
||||||
|
</div>
|
||||||
|
<!-- style="pointer-events: none;" -->
|
||||||
|
<div v-if="props.pdfObj.numberOfPdf === 2" :class="ispointer ? 'ispointer' : ''">
|
||||||
|
<canvas ref="fabriccanvas1" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -16,12 +26,17 @@ import {
|
||||||
defineProps,
|
defineProps,
|
||||||
defineExpose,
|
defineExpose,
|
||||||
nextTick,
|
nextTick,
|
||||||
defineEmits
|
defineEmits,watchEffect
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { fabric } from 'fabric'
|
// import { fabric } from 'fabric'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { handleevent, savecanvsStore, initcanvasdata, displayData } from '@/utils/pdfAndFabric'
|
import { handleevent, savecanvsStore, initcanvasdata, displayData } from '@/utils/pdfAndFabric'
|
||||||
|
import { fabricVue, TYPES } from '@/plugins/fabric'
|
||||||
|
import { updateSmartBookMarkContent, addsmartBookMark,getBookMarkById } from '@/api/eTextbook/index'
|
||||||
|
import {useToolState} from '@/store/modules/tool'
|
||||||
|
const { ipcRenderer } = require('electron')
|
||||||
|
|
||||||
|
const toolState = useToolState();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
pdfObj: {
|
pdfObj: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -32,13 +47,16 @@ const props = defineProps({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const ispointer = ref(false) //是否画笔模式
|
||||||
// canvas的所有数据
|
// canvas的所有数据
|
||||||
const canvsStore = reactive({
|
const canvsStore = reactive({
|
||||||
id: 'xxxx',
|
|
||||||
pageArr: []
|
pageArr: []
|
||||||
})
|
})
|
||||||
const fabriccanvas = ref(null)
|
const fabriccanvas = ref(null)
|
||||||
const fabriccanvas1 = ref(null)
|
const fabriccanvas1 = ref(null)
|
||||||
|
|
||||||
|
const canvasFabricVue = ref(null)
|
||||||
|
const canvas1FabricVue = ref(null)
|
||||||
// 页面总数
|
// 页面总数
|
||||||
const numPagesTotal = ref(0)
|
const numPagesTotal = ref(0)
|
||||||
const imgarr = ref([])
|
const imgarr = ref([])
|
||||||
|
@ -50,9 +68,9 @@ const renderPage = async (canvasobj) => {
|
||||||
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
||||||
// 渲染当前页
|
// 渲染当前页
|
||||||
const page = await pdf.getPage(canvasobj.page)
|
const page = await pdf.getPage(canvasobj.page)
|
||||||
var screenWidth = window.innerWidth/2-100;
|
var screenWidth = window.innerWidth / 2 - 100
|
||||||
var screenHeight = window.innerHeight;
|
var screenHeight = window.innerHeight
|
||||||
const viewport = page.getViewport({ scale:2})
|
const viewport = page.getViewport({ scale: 2 })
|
||||||
|
|
||||||
const canvasElement = canvasobj.canvas
|
const canvasElement = canvasobj.canvas
|
||||||
canvasElement.width = viewport.width
|
canvasElement.width = viewport.width
|
||||||
|
@ -61,6 +79,8 @@ const renderPage = async (canvasobj) => {
|
||||||
canvasContext: canvasobj.context,
|
canvasContext: canvasobj.context,
|
||||||
viewport: viewport
|
viewport: viewport
|
||||||
}
|
}
|
||||||
|
// console.log(renderContext,22222222222222222222)
|
||||||
|
|
||||||
page.render(renderContext).promise.then((res) => {
|
page.render(renderContext).promise.then((res) => {
|
||||||
const img = document.createElement('img')
|
const img = document.createElement('img')
|
||||||
img.src = canvasobj.canvas.toDataURL('image/png')
|
img.src = canvasobj.canvas.toDataURL('image/png')
|
||||||
|
@ -71,33 +91,68 @@ const renderPage = async (canvasobj) => {
|
||||||
// 根据传过来的pdf对象 判断改渲染哪一个fabric
|
// 根据传过来的pdf对象 判断改渲染哪一个fabric
|
||||||
if (props.pdfObj.numberOfPdf == 2) {
|
if (props.pdfObj.numberOfPdf == 2) {
|
||||||
if (canvasobj.index == 0) {
|
if (canvasobj.index == 0) {
|
||||||
|
canvasFabricVue.value.canvas.setWidth(screenWidth)
|
||||||
fabriccanvas.value.setWidth(screenWidth)
|
canvasFabricVue.value.canvas.setHeight(screenHeight)
|
||||||
fabriccanvas.value.setHeight(screenHeight)
|
// updateCanvasBackgroundImage(canvasFabricVue,img)
|
||||||
displayData(fabriccanvas, canvsStore, canvasobj, fabric, img)
|
displayData(canvasFabricVue, canvsStore, canvasobj, fabric, img)
|
||||||
} else {
|
} else {
|
||||||
fabriccanvas1.value.setWidth(screenWidth)
|
canvas1FabricVue.value.canvas.setWidth(screenWidth)
|
||||||
fabriccanvas1.value.setHeight(screenHeight)
|
canvas1FabricVue.value.canvas.setHeight(screenHeight)
|
||||||
displayData(fabriccanvas1, canvsStore, canvasobj, fabric, img)
|
displayData(canvas1FabricVue, canvsStore, canvasobj, fabric, img)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fabriccanvas.value.setWidth(screenWidth)
|
canvasFabricVue.value.canvas.setHeight(screenHeight)
|
||||||
fabriccanvas.value.setHeight(screenHeight)
|
displayData(canvasFabricVue, canvsStore, canvasobj, fabric, img)
|
||||||
displayData(fabriccanvas, canvsStore, canvasobj, fabric, img)
|
|
||||||
}
|
}
|
||||||
// console.log(imgarr.value)
|
|
||||||
img.remove()
|
img.remove()
|
||||||
}
|
}
|
||||||
// 判断imgarr的JSONdata在canvsStore.pageArr有没有
|
// 判断imgarr的JSONdata在canvsStore.pageArr有没有
|
||||||
canvsStore.pageArr.forEach((item) => {
|
// canvsStore.pageArr.forEach((item) => {
|
||||||
if (item.page == canvasobj.page) {
|
// if (item.page == canvasobj.page) {
|
||||||
imgarr.value.forEach((img) => {
|
// imgarr.value.forEach((img) => {
|
||||||
if (img.page == canvasobj.page) {
|
// if (img.page == canvasobj.page) {
|
||||||
img.JSONdata = item.JSONdata
|
// img.JSONdata = item.JSONdata
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 保存数据
|
||||||
|
const savaDataStore = () => {
|
||||||
|
imgarr.value.forEach((a) => {
|
||||||
|
if (a.index == 0) {
|
||||||
|
a.JSONdata = canvasFabricVue.value.canvas.toJSON()
|
||||||
|
} else {
|
||||||
|
a.JSONdata = canvas1FabricVue.value.canvas.toJSON()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const nameMap = new Map(canvsStore.pageArr.map((item) => [item.page, item.id]))
|
||||||
|
// 创建一个用于存储所有异步操作的数组
|
||||||
|
let promises = []
|
||||||
|
imgarr.value.forEach((item) => {
|
||||||
|
if (nameMap.has(item.page)) {
|
||||||
|
const params = {
|
||||||
|
id: nameMap.get(item.page),
|
||||||
|
contentData: JSON.stringify(item.JSONdata.objects)
|
||||||
|
}
|
||||||
|
promises.push(updateSmartBookMarkContent([params]))
|
||||||
|
} else {
|
||||||
|
promises.push(addsmartBookMark({
|
||||||
|
pageNum: item.page,
|
||||||
|
contentData: JSON.stringify(item.JSONdata.objects),
|
||||||
|
bookId: props.pdfObj.bookId,
|
||||||
|
type: '教材',
|
||||||
|
source: 'smarttalk'
|
||||||
|
}))
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Promise.all(promises).then(res=>{
|
||||||
|
toolState.isPdfWin=false
|
||||||
|
toolState.showBoardAll=true //恢复默认值
|
||||||
|
ipcRenderer.invoke('tool-sphere:reset') //重置tool状态
|
||||||
|
ipcRenderer.send('open-PDF:minimize')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const updatePage = (canvasobj) => {
|
const updatePage = (canvasobj) => {
|
||||||
|
@ -108,16 +163,54 @@ const loadPdf = async (canvasobj) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const initPdf = async (type = 'default') => {
|
const initPdf = async (type = 'default') => {
|
||||||
|
imgarr.value.forEach((a) => {
|
||||||
|
if (a.index == 0) {
|
||||||
|
a.JSONdata = canvasFabricVue.value.canvas.toJSON()
|
||||||
|
} else {
|
||||||
|
a.JSONdata = canvas1FabricVue.value.canvas.toJSON()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (type != 'default') {
|
||||||
|
const nameMap = new Map(canvsStore.pageArr.map((item) => [item.page, item.id]))
|
||||||
|
// 创建一个用于存储所有异步操作的数组
|
||||||
|
let promises = []
|
||||||
|
imgarr.value.forEach((item) => {
|
||||||
|
if (nameMap.has(item.page)) {
|
||||||
|
const params = {
|
||||||
|
id: nameMap.get(item.page),
|
||||||
|
contentData: JSON.stringify(item.JSONdata.objects)
|
||||||
|
}
|
||||||
|
promises.push(updateSmartBookMarkContent([params]))
|
||||||
|
} else {
|
||||||
|
promises.push(addsmartBookMark({
|
||||||
|
pageNum: item.page,
|
||||||
|
contentData: JSON.stringify(item.JSONdata.objects),
|
||||||
|
bookId: props.pdfObj.bookId,
|
||||||
|
type: '教材',
|
||||||
|
source: 'smarttalk'
|
||||||
|
}))
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Promise.all(promises).then(res=>{
|
||||||
|
getBookMarkById(props.pdfObj.bookId).then(res=>{
|
||||||
|
const pageArr=getUniqueArrayByLastOccurrence(res.data)
|
||||||
|
canvsStore.pageArr=[]
|
||||||
|
pageArr.forEach((a) => {
|
||||||
|
canvsStore.pageArr.push({ page: a.pageNum, id: a.id, JSONdata: a.contentData })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
// 保存数据
|
// 保存数据
|
||||||
savecanvsStore(imgarr, canvsStore)
|
// savecanvsStore(imgarr, canvsStore)
|
||||||
// initcanvasdata(fabriccanvas)
|
|
||||||
// initcanvasdata(fabriccanvas1)
|
if (props.pdfObj.numberOfPdf == 1) {
|
||||||
// 单页模式
|
// imgarr.value[0]
|
||||||
if (type == 'restone') {
|
canvasFabricVue.value.history.clean()
|
||||||
// 清除 canvas 上的所有对象
|
} else {
|
||||||
fabriccanvas1.value.clear()
|
canvasFabricVue.value.history.clean()
|
||||||
// 释放 canvas 的资源
|
canvas1FabricVue.value.history.clean()
|
||||||
fabriccanvas1.value.dispose()
|
|
||||||
}
|
}
|
||||||
// 清除现有 canvas 元素的内容
|
// 清除现有 canvas 元素的内容
|
||||||
canvasNumbsValue.value.forEach((canvasObj) => {
|
canvasNumbsValue.value.forEach((canvasObj) => {
|
||||||
|
@ -149,7 +242,6 @@ const initPdf = async (type = 'default') => {
|
||||||
} else {
|
} else {
|
||||||
canvasNumbsValue.value[i].page = props.pdfObj.numPages + 1
|
canvasNumbsValue.value[i].page = props.pdfObj.numPages + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasNumbsValue.value[i].index = i
|
canvasNumbsValue.value[i].index = i
|
||||||
// 加载FabricVue
|
// 加载FabricVue
|
||||||
await loadPdf(canvasNumbsValue.value[i])
|
await loadPdf(canvasNumbsValue.value[i])
|
||||||
|
@ -157,47 +249,144 @@ const initPdf = async (type = 'default') => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//根据page去重
|
||||||
|
const getUniqueArrayByLastOccurrence=(array)=> {
|
||||||
|
const uniqueItems = array.reduce((acc, current) => {
|
||||||
|
// 使用 Map 来跟踪最后一个出现的 pageNum 和它的对象
|
||||||
|
acc.set(current.pageNum, current);
|
||||||
|
return acc;
|
||||||
|
}, new Map());
|
||||||
|
|
||||||
|
// 将 Map 的值转换回数组
|
||||||
|
const resultArray = Array.from(uniqueItems.values());
|
||||||
|
|
||||||
|
return resultArray;
|
||||||
|
}
|
||||||
const initPdfone = async () => {
|
const initPdfone = async () => {
|
||||||
setTimeout(() => {
|
setTimeout(async () => {
|
||||||
fabriccanvas1.value = new fabric.Canvas('pdf-fabric1')
|
const option = { freeDrawingCursor: 'default' }
|
||||||
fabriccanvas1.value.isDrawingMode = true
|
const canvas2 = new fabricVue()
|
||||||
fabriccanvas1.value.freeDrawingBrush.color = '#A33AFE'
|
await canvas2.initCanvas(fabriccanvas1.value, option)
|
||||||
fabriccanvas1.value.freeDrawingCursor = 'default'
|
canvas2.canvas.setWidth(window.innerWidth / 2 - 100)
|
||||||
fabriccanvas1.value.setWidth(595)
|
canvas1FabricVue.value = canvas2
|
||||||
handleevent(fabriccanvas1.value, imgarr, 'two')
|
await initPdf('addOnePage')
|
||||||
}, 0)
|
}, 0)
|
||||||
initPdf('addOnePage')
|
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
|
// 创建canvas转化成图片
|
||||||
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
||||||
numPagesTotal.value = pdf.numPages
|
numPagesTotal.value = pdf.numPages
|
||||||
// console.log(pdf)
|
|
||||||
// 初始化fabriccanvas
|
// 初始化fabriccanvas
|
||||||
fabriccanvas.value = new fabric.Canvas('pdf-fabric')
|
const option = { freeDrawingCursor: 'default' }
|
||||||
fabriccanvas.value.setWidth(595)
|
const canvas1 = new fabricVue()
|
||||||
fabriccanvas.value.isDrawingMode = true
|
// canvas1.boardConfig.mode= TYPES.ActionMode.OTHER
|
||||||
fabriccanvas.value.freeDrawingBrush.color = '#A33AFE'
|
// canvas1.boardConfig.mode= TYPES.ActionMode.ERASE
|
||||||
fabriccanvas.value.freeDrawingCursor = 'default'
|
await canvas1.initCanvas(fabriccanvas.value, option)
|
||||||
|
canvas1.canvas.setWidth(window.innerWidth / 2 - 100)
|
||||||
fabriccanvas1.value = new fabric.Canvas('pdf-fabric1')
|
canvasFabricVue.value = canvas1
|
||||||
fabriccanvas1.value.isDrawingMode = true
|
const canvas2 = new fabricVue()
|
||||||
fabriccanvas1.value.freeDrawingBrush.color = '#A33AFE'
|
await canvas2.initCanvas(fabriccanvas1.value, option)
|
||||||
fabriccanvas1.value.freeDrawingCursor = 'default'
|
canvas2.canvas.setWidth(window.innerWidth / 2 - 100)
|
||||||
fabriccanvas1.value.setWidth(595)
|
// canvas2.canvas.isDrawingMode=false
|
||||||
|
canvas1FabricVue.value = canvas2
|
||||||
|
window.test = { canvas1, canvas2 }
|
||||||
emit('update:numPagesTotal', pdf.numPages)
|
emit('update:numPagesTotal', pdf.numPages)
|
||||||
initPdf()
|
|
||||||
|
if (props.pdfObj.allPageData.length) {
|
||||||
|
props.pdfObj.allPageData.forEach((a) => {
|
||||||
|
if (a.pageNum == 1 || a.pageNum == 2) {
|
||||||
|
canvsStore.pageArr.push({ page: a.pageNum, id: a.id, JSONdata: a.contentData })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await initPdf()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
ElMessage.error('pdf文件错误')
|
ElMessage.error('pdf文件错误')
|
||||||
}
|
}
|
||||||
|
setToolStatus()
|
||||||
// 监听2个canvas事件
|
// 监听2个canvas事件
|
||||||
handleevent(fabriccanvas.value, imgarr)
|
// handleevent(fabriccanvas.value, imgarr)
|
||||||
handleevent(fabriccanvas1.value, imgarr, 'two')
|
// handleevent(fabriccanvas1.value, imgarr, 'two')
|
||||||
})
|
})
|
||||||
|
// zdg: 设置-底部工具栏-状态
|
||||||
|
const setToolStatus = () => {
|
||||||
|
toolState.showBoardAll = false
|
||||||
|
}
|
||||||
|
// 判断元素是否加载完成
|
||||||
|
const handleMode = (vale,type)=>{
|
||||||
|
if(vale=='select'){
|
||||||
|
ispointer.value=true
|
||||||
|
}else{
|
||||||
|
ispointer.value=false
|
||||||
|
}
|
||||||
|
switch(vale) {
|
||||||
|
case 'select': // 选择模式
|
||||||
|
canvasFabricVue.value?.handleMode(TYPES.ActionMode.OTHER)
|
||||||
|
canvas1FabricVue.value?.handleMode(TYPES.ActionMode.OTHER)
|
||||||
|
break
|
||||||
|
case 'brush': // 画笔模式
|
||||||
|
canvasFabricVue.value?.handleMode(TYPES.ActionMode.DRAW)
|
||||||
|
canvasFabricVue.value.canvas.freeDrawingCursor = 'default'
|
||||||
|
canvas1FabricVue.value?.handleMode(TYPES.ActionMode.DRAW)
|
||||||
|
canvas1FabricVue.value.canvas.freeDrawingCursor = 'default'
|
||||||
|
break
|
||||||
|
case 'erase': // 板擦模式
|
||||||
|
canvasFabricVue.value?.handleMode(TYPES.ActionMode.ERASE)
|
||||||
|
canvas1FabricVue.value?.handleMode(TYPES.ActionMode.ERASE)
|
||||||
|
break
|
||||||
|
case 'clear': // 清空画布
|
||||||
|
clearCanvas()
|
||||||
|
// canvas1FabricVue.value.history?.clean()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 清空canvas
|
||||||
|
const clearCanvas=()=>{
|
||||||
|
if(canvasFabricVue.value){
|
||||||
|
const objects = canvasFabricVue.value.canvas.getObjects();
|
||||||
|
objects.forEach((obj) => {
|
||||||
|
// 检查对象是否是背景
|
||||||
|
if (obj !== canvasFabricVue.value.canvas.backgroundImage) {
|
||||||
|
// 删除背景之外的对象
|
||||||
|
canvasFabricVue.value.canvas.remove(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
canvasFabricVue.value.canvas.renderAll();
|
||||||
|
}
|
||||||
|
if(canvas1FabricVue.value){
|
||||||
|
const objects = canvas1FabricVue.value.canvas.getObjects();
|
||||||
|
objects.forEach((obj) => {
|
||||||
|
// 检查对象是否是背景
|
||||||
|
if (obj !== canvas1FabricVue.value.canvas.backgroundImage) {
|
||||||
|
// 删除背景之外的对象
|
||||||
|
canvas1FabricVue.value.canvas.remove(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas1FabricVue.value.canvas.renderAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const watchToolState=()=>{
|
||||||
|
if(toolState.showBoardAll){
|
||||||
|
setTimeout(() => {
|
||||||
|
toolState.showBoardAll=false
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
// 加载工具
|
||||||
|
handleMode(toolState.model)
|
||||||
|
|
||||||
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
initPdf,
|
initPdf,
|
||||||
initPdfone
|
initPdfone,
|
||||||
|
savaDataStore
|
||||||
|
})
|
||||||
|
watchEffect(() => {
|
||||||
|
console.log(toolState.model,'监听')
|
||||||
|
watchToolState() //监听工具栏
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -207,6 +396,8 @@ defineExpose({
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
max-height: 100vh;
|
||||||
}
|
}
|
||||||
.pdfAdnFabric {
|
.pdfAdnFabric {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -217,4 +408,7 @@ defineExpose({
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ispointer {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -1615,6 +1615,7 @@ export class fabricVue {
|
||||||
break
|
break
|
||||||
case TYPES.ActionMode.OTHER: // 其他(工具选择)
|
case TYPES.ActionMode.OTHER: // 其他(工具选择)
|
||||||
this.canvas.isDrawingMode = false
|
this.canvas.isDrawingMode = false
|
||||||
|
objectSet.selectable = false
|
||||||
this.canvas.freeDrawingCursor = 'default'
|
this.canvas.freeDrawingCursor = 'default'
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* 共享数据状态-多窗口
|
* 共享数据状态-多窗口
|
||||||
*/
|
*/
|
||||||
const { ipcRenderer } = require('electron') // app使用
|
const isNode = typeof require !== 'undefined' // 是否支持node函数
|
||||||
|
const { ipcRenderer } = isNode?require('electron'):{} // app使用
|
||||||
export function shareStorePlugin({store}) {
|
export function shareStorePlugin({store}) {
|
||||||
store.$subscribe(() => { // 自动同步
|
store.$subscribe(() => { // 自动同步
|
||||||
// 在存储变化的时候执行
|
// 在存储变化的时候执行
|
||||||
|
@ -19,15 +20,16 @@ export function shareStorePlugin({store}) {
|
||||||
function stateSync(store) {
|
function stateSync(store) {
|
||||||
const storeName = store.$id
|
const storeName = store.$id
|
||||||
const jsonStr = JSON.stringify(store.$state)
|
const jsonStr = JSON.stringify(store.$state)
|
||||||
|
// console.log('state-change', jsonStr, storeName)
|
||||||
// 通知主线程更新
|
// 通知主线程更新
|
||||||
ipcRenderer.invoke('pinia-state-change', storeName, jsonStr)
|
ipcRenderer?.invoke('pinia-state-change', storeName, jsonStr)
|
||||||
}
|
}
|
||||||
// 同步数据-接收主线程消息
|
// 同步数据-接收主线程消息
|
||||||
function stateChange(store) {
|
function stateChange(store) {
|
||||||
const storeName = store.$id
|
const storeName = store.$id
|
||||||
ipcRenderer.on('pinia-state-set', (e, sName, jsonStr) => {
|
ipcRenderer?.on('pinia-state-set', (e, sName, jsonStr) => {
|
||||||
if (sName == storeName) { // 更新对应数据
|
if (sName == storeName) { // 更新对应数据
|
||||||
console.log('state-set', jsonStr, sName)
|
// console.log('state-set', jsonStr, sName)
|
||||||
const curJson = JSON.stringify(store.$state) // 当前数据
|
const curJson = JSON.stringify(store.$state) // 当前数据
|
||||||
const isUp = curJson != jsonStr // 不同的时候才写入,不然会导致触发数据变化监听,导致死循环
|
const isUp = curJson != jsonStr // 不同的时候才写入,不然会导致触发数据变化监听,导致死循环
|
||||||
if (!isUp) return
|
if (!isUp) return
|
||||||
|
|
|
@ -7,6 +7,8 @@ export const useToolState = defineStore('tool', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
model: 'select', // 悬浮球-当前模式
|
model: 'select', // 悬浮球-当前模式
|
||||||
showBoardAll: false, // 全屏画板-是否显示
|
showBoardAll: false, // 全屏画板-是否显示
|
||||||
|
isPdfWin: false, // pdf窗口是否打开
|
||||||
|
isToolWin: false, // 工具窗口是否打开
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
// 所有事件
|
||||||
|
export function handleevent(canvas, imgarr, type = 'defalut') {
|
||||||
|
// // 鼠标按下
|
||||||
|
// canvas.on('mouse:down', function (e) {})
|
||||||
|
// // // 监听鼠标移动事件
|
||||||
|
// // canvas.on('mouse:move', (options) => {
|
||||||
|
// // console.log('Mouse move event:', options);
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// // 监听鼠标释放事件
|
||||||
|
// canvas.on('mouse:up', (options) => {
|
||||||
|
// //判断是点击的哪一个
|
||||||
|
// if (type == 'defalut') {
|
||||||
|
// if (imgarr.value[0].index == 0) {
|
||||||
|
// imgarr.value[0].JSONdata = canvas.toJSON()
|
||||||
|
// }
|
||||||
|
// if (imgarr.value[1]?.index == 0) {
|
||||||
|
// imgarr.value[1].JSONdata = canvas.toJSON()
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (imgarr.value[0].index == 1) {
|
||||||
|
// imgarr.value[0].JSONdata = canvas.toJSON()
|
||||||
|
// }
|
||||||
|
// if (imgarr.value[1]?.index == 1) {
|
||||||
|
// imgarr.value[1].JSONdata = canvas.toJSON()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// console.log(imgarr.value)
|
||||||
|
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
// 保存数据
|
||||||
|
export function savecanvsStore(imgarr, canvsStore) {
|
||||||
|
// canvsStore.pageArr = mergeAndReplace(canvsStore.pageArr, imgarr.value)
|
||||||
|
}
|
||||||
|
// 重显数据
|
||||||
|
export function displayData(canvas, canvsStore, canvasobj, fabric, img) {
|
||||||
|
// // 初始化
|
||||||
|
// if (!canvsStore.pageArr.length) {
|
||||||
|
// fabric.Image.fromURL(img.src, (img) => {
|
||||||
|
// img.set({
|
||||||
|
// left: 0,
|
||||||
|
// top: 0,
|
||||||
|
// scaleX: canvas.value.width / img.width,
|
||||||
|
// scaleY: canvas.value.height / img.height
|
||||||
|
// })
|
||||||
|
// canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value))
|
||||||
|
// })
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// canvsStore.pageArr.forEach((item) => {
|
||||||
|
// //初始化
|
||||||
|
// if (item.page == canvasobj.page) {
|
||||||
|
// // canvas.value.clear() // 清除 Canvas
|
||||||
|
// // console.log(item.JSONdata, '找到一样的数据')
|
||||||
|
// canvas.value.loadFromJSON(item.JSONdata, () => {
|
||||||
|
// // 在所有对象加载完成后重新渲染画布
|
||||||
|
// canvas.value.renderAll.bind(canvas.value)
|
||||||
|
// canvas.value.renderAll()
|
||||||
|
// // requestAnimationFrame(() => {
|
||||||
|
// // // 渲染所有对象
|
||||||
|
|
||||||
|
// // })
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// // 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
||||||
|
// // // 清除 Canvas
|
||||||
|
// canvas.value.clear()
|
||||||
|
// requestAnimationFrame(function () {
|
||||||
|
// fabric.Image.fromURL(img.src, (img) => {
|
||||||
|
// img.set({
|
||||||
|
// left: 0,
|
||||||
|
// top: 0,
|
||||||
|
// scaleX: canvas.value.width / img.width,
|
||||||
|
// scaleY: canvas.value.height / img.height
|
||||||
|
// })
|
||||||
|
// canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value))
|
||||||
|
// })
|
||||||
|
// // 渲染所有对象
|
||||||
|
// canvas.value.renderAll.bind(canvas.value)
|
||||||
|
// canvas.value.renderAll()
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
//page 一样替换
|
||||||
|
const mergeAndReplace = (arr1, arr2) => {
|
||||||
|
// // 用于存储替换后的数组
|
||||||
|
// const resultArray = array1.map(item1 => {
|
||||||
|
// // 在 array2 中查找 page 相同的对象
|
||||||
|
// const replacement = array2.find(item2 => item2.page == item1.page);
|
||||||
|
// // 如果找到替换对象,则返回替换对象,否则返回原对象
|
||||||
|
// return replacement ? replacement : item1;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // 将 array2 中 page 不在 array1 中的对象追加到结果数组中
|
||||||
|
// array2.forEach(item2 => {
|
||||||
|
// const existsInArray1 = array1.some(item1 => item1.page == item2.page);
|
||||||
|
// if (!existsInArray1) {
|
||||||
|
// resultArray.push(item2);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return resultArray;
|
||||||
|
|
||||||
|
// 创建一个映射,将 arr2 中的对象按 page 属性存储
|
||||||
|
let map = new Map(arr2.map((item) => [item.page, item]))
|
||||||
|
|
||||||
|
// 使用 map 替换 arr1 中相应 page 的对象,并添加 arr2 中的对象
|
||||||
|
arr1 = arr1.map((item) => (map.has(item.page) ? map.get(item.page) : item))
|
||||||
|
|
||||||
|
// 将 map 中存在但 arr1 中不存在的对象添加到 arr1
|
||||||
|
for (let [page, obj] of map) {
|
||||||
|
if (!arr1.some((item) => item.page === page)) {
|
||||||
|
arr1.push(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化数据
|
||||||
|
export function initcanvasdata(canvas) {
|
||||||
|
canvas.value.clear() // 清除 Canvas
|
||||||
|
// 设置画布的背景色或其他属性
|
||||||
|
canvas.value.backgroundColor = 'rgba(255, 255, 255, 1)' // 白色背景
|
||||||
|
|
||||||
|
// 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
// 渲染所有对象
|
||||||
|
canvas.value.renderAll.bind(canvas.value)
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,108 +1,187 @@
|
||||||
|
|
||||||
// 所有事件
|
// 所有事件
|
||||||
export function handleevent(canvas, imgarr, type = 'defalut') {
|
export function handleevent(canvas, imgarr, type = 'defalut') {
|
||||||
// 鼠标按下
|
// // 鼠标按下
|
||||||
canvas.on('mouse:down', function (e) {})
|
// canvas.on('mouse:down', function (e) {})
|
||||||
// // 监听鼠标移动事件
|
// // // 监听鼠标移动事件
|
||||||
// canvas.on('mouse:move', (options) => {
|
// // canvas.on('mouse:move', (options) => {
|
||||||
// console.log('Mouse move event:', options);
|
// // console.log('Mouse move event:', options);
|
||||||
// });
|
// // });
|
||||||
|
|
||||||
// 监听鼠标释放事件
|
// // 监听鼠标释放事件
|
||||||
canvas.on('mouse:up', (options) => {
|
// canvas.on('mouse:up', (options) => {
|
||||||
//判断是点击的哪一个
|
// //判断是点击的哪一个
|
||||||
if (type == 'defalut') {
|
// if (type == 'defalut') {
|
||||||
if (imgarr.value[0].index == 0) {
|
// if (imgarr.value[0].index == 0) {
|
||||||
imgarr.value[0].JSONdata = canvas.toJSON()
|
// imgarr.value[0].JSONdata = canvas.toJSON()
|
||||||
}
|
// }
|
||||||
if (imgarr.value[1]?.index == 0) {
|
// if (imgarr.value[1]?.index == 0) {
|
||||||
imgarr.value[1].JSONdata = canvas.toJSON()
|
// imgarr.value[1].JSONdata = canvas.toJSON()
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
if (imgarr.value[0].index == 1) {
|
// if (imgarr.value[0].index == 1) {
|
||||||
imgarr.value[0].JSONdata = canvas.toJSON()
|
// imgarr.value[0].JSONdata = canvas.toJSON()
|
||||||
}
|
// }
|
||||||
if (imgarr.value[1]?.index == 1) {
|
// if (imgarr.value[1]?.index == 1) {
|
||||||
imgarr.value[1].JSONdata = canvas.toJSON()
|
// imgarr.value[1].JSONdata = canvas.toJSON()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
console.log(imgarr.value)
|
// console.log(imgarr.value)
|
||||||
|
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
// 保存数据
|
// 保存数据
|
||||||
export function savecanvsStore(imgarr, canvsStore) {
|
export function savecanvsStore(imgarr, canvsStore) {
|
||||||
canvsStore.pageArr = mergeAndReplace(canvsStore.pageArr, imgarr.value)
|
canvsStore.pageArr = mergeAndReplace(canvsStore.pageArr, imgarr.value)
|
||||||
}
|
}
|
||||||
// 重显数据
|
// 重显数据
|
||||||
export function displayData(canvas, canvsStore, canvasobj, fabric, img) {
|
export function displayData(FabricVue, canvsStore, canvasobj, fabric, img) {
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
if (!canvsStore.pageArr.length) {
|
const canvas = FabricVue.value.canvas
|
||||||
fabric.Image.fromURL(img.src, (img) => {
|
if (!canvas) {
|
||||||
img.set({
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
scaleX: canvas.value.width / img.width,
|
|
||||||
scaleY: canvas.value.height / img.height
|
|
||||||
})
|
|
||||||
canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value))
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
canvsStore.pageArr.forEach((item) => {
|
if (!canvsStore.pageArr.length) {
|
||||||
//初始化
|
fabric.Image.fromURL(
|
||||||
if (item.page == canvasobj.page) {
|
img.src,
|
||||||
// canvas.value.clear() // 清除 Canvas
|
(image) => {
|
||||||
// console.log(item.JSONdata, '找到一样的数据')
|
image.set({
|
||||||
canvas.value.loadFromJSON(item.JSONdata, () => {
|
|
||||||
// 在所有对象加载完成后重新渲染画布
|
|
||||||
canvas.value.renderAll.bind(canvas.value)
|
|
||||||
canvas.value.renderAll()
|
|
||||||
// requestAnimationFrame(() => {
|
|
||||||
// // 渲染所有对象
|
|
||||||
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
|
||||||
// // 清除 Canvas
|
|
||||||
canvas.value.clear()
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
fabric.Image.fromURL(img.src, (img) => {
|
|
||||||
img.set({
|
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
scaleX: canvas.value.width / img.width,
|
scaleX: canvas.width / img.width,
|
||||||
scaleY: canvas.value.height / img.height
|
scaleY: canvas.height / img.height,
|
||||||
|
erasable: false // 不允许擦拭
|
||||||
})
|
})
|
||||||
canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value))
|
// FabricVue.setBackgroundImage(image, FabricVue.renderAll.bind(FabricVue))
|
||||||
|
// setBackgroundImage(image,FabricVue)
|
||||||
|
// canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||||
|
|
||||||
|
canvas.setBackgroundImage(image, () => {
|
||||||
|
canvas.renderAll.bind(canvas)
|
||||||
|
FabricVue.value.render()
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
{crossOrigin: 'anonymous'}
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const isfind=findObjectByPage(canvsStore.pageArr,canvasobj.page)
|
||||||
|
if(isfind){
|
||||||
|
const canvdata={
|
||||||
|
objects:JSON.parse(isfind.JSONdata),
|
||||||
|
version: "5.3.0"
|
||||||
|
}
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
canvas.loadFromJSON(canvdata, () => {
|
||||||
|
// 在所有对象加载完成后重新渲染画布
|
||||||
|
// Utils.handleCanvasJSONLoaded(canvas)
|
||||||
|
canvas.requestRenderAll() // 批量重绘
|
||||||
|
})
|
||||||
|
fabric.Image.fromURL(
|
||||||
|
img.src,
|
||||||
|
(image) => {
|
||||||
|
image.set({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
scaleX: canvas.width / img.width,
|
||||||
|
scaleY: canvas.height / img.height,
|
||||||
|
selectable: false,
|
||||||
|
evented: false,
|
||||||
|
erasable: false // 不允许擦拭
|
||||||
|
})
|
||||||
|
// canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||||
|
canvas.setBackgroundImage(image, () => {
|
||||||
|
canvas.renderAll.bind(canvas)
|
||||||
|
FabricVue.value.render()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{crossOrigin: 'anonymous'}
|
||||||
|
)
|
||||||
// 渲染所有对象
|
// 渲染所有对象
|
||||||
canvas.value.renderAll.bind(canvas.value)
|
canvas.requestRenderAll() // 批量重绘
|
||||||
canvas.value.renderAll()
|
})
|
||||||
|
}else{
|
||||||
|
// 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
||||||
|
// // 清除 Canvas
|
||||||
|
// canvas.clear()
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
fabric.Image.fromURL(
|
||||||
|
img.src,
|
||||||
|
(image) => {
|
||||||
|
image.set({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
scaleX: canvas.width / img.width,
|
||||||
|
scaleY: canvas.height / img.height,
|
||||||
|
selectable: false,
|
||||||
|
evented: false,
|
||||||
|
erasable: false // 不允许擦拭
|
||||||
|
})
|
||||||
|
// canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||||
|
canvas.setBackgroundImage(image, () => {
|
||||||
|
canvas.renderAll.bind(canvas)
|
||||||
|
FabricVue.value.render()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{crossOrigin: 'anonymous'}
|
||||||
|
)
|
||||||
|
// 渲染所有对象
|
||||||
|
canvas.requestRenderAll() // 批量重绘
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
// canvsStore.pageArr.forEach((item) => {
|
||||||
|
// //初始化
|
||||||
|
// if (item.page == canvasobj.page) {
|
||||||
|
// // item.JSONdata
|
||||||
|
// canvas.loadFromJSON(JSON.parse(item.JSONdata), () => {
|
||||||
|
// // 在所有对象加载完成后重新渲染画布
|
||||||
|
// // Utils.handleCanvasJSONLoaded(canvas)
|
||||||
|
// canvas.requestRenderAll() // 批量重绘
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
|
||||||
|
// // 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
||||||
|
// // // 清除 Canvas
|
||||||
|
// // canvas.clear()
|
||||||
|
// requestAnimationFrame(function () {
|
||||||
|
// fabric.Image.fromURL(
|
||||||
|
// img.src,
|
||||||
|
// (image) => {
|
||||||
|
// image.set({
|
||||||
|
// left: 0,
|
||||||
|
// top: 0,
|
||||||
|
// scaleX: canvas.width / img.width,
|
||||||
|
// scaleY: canvas.height / img.height,
|
||||||
|
// selectable: false,
|
||||||
|
// evented: false,
|
||||||
|
// erasable: false // 不允许擦拭
|
||||||
|
// })
|
||||||
|
// // canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||||
|
// canvas.setBackgroundImage(image, () => {
|
||||||
|
// canvas.renderAll.bind(canvas)
|
||||||
|
// FabricVue.value.render()
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// {crossOrigin: 'anonymous'}
|
||||||
|
// )
|
||||||
|
// // 渲染所有对象
|
||||||
|
// canvas.requestRenderAll() // 批量重绘
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
// 找到page一样的
|
||||||
|
const findObjectByPage=(array, page)=> {
|
||||||
|
const foundObject = array.find(obj => obj.page === page);
|
||||||
|
return foundObject || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//page 一样替换
|
//page 一样替换
|
||||||
const mergeAndReplace = (arr1, arr2) => {
|
const mergeAndReplace = (arr1, arr2) => {
|
||||||
// // 用于存储替换后的数组
|
|
||||||
// const resultArray = array1.map(item1 => {
|
|
||||||
// // 在 array2 中查找 page 相同的对象
|
|
||||||
// const replacement = array2.find(item2 => item2.page == item1.page);
|
|
||||||
// // 如果找到替换对象,则返回替换对象,否则返回原对象
|
|
||||||
// return replacement ? replacement : item1;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // 将 array2 中 page 不在 array1 中的对象追加到结果数组中
|
|
||||||
// array2.forEach(item2 => {
|
|
||||||
// const existsInArray1 = array1.some(item1 => item1.page == item2.page);
|
|
||||||
// if (!existsInArray1) {
|
|
||||||
// resultArray.push(item2);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return resultArray;
|
|
||||||
|
|
||||||
// 创建一个映射,将 arr2 中的对象按 page 属性存储
|
// 创建一个映射,将 arr2 中的对象按 page 属性存储
|
||||||
let map = new Map(arr2.map((item) => [item.page, item]))
|
let map = new Map(arr2.map((item) => [item.page, item]))
|
||||||
|
|
|
@ -6,14 +6,17 @@
|
||||||
// Remote.app.getAppPath() E:\njys-work\AIx_Smarttalk\dist\win-unpacked\resources\app.asar
|
// Remote.app.getAppPath() E:\njys-work\AIx_Smarttalk\dist\win-unpacked\resources\app.asar
|
||||||
// path.join(__dirname) 根目录 E:\njys-work\AIx_Smarttalk\dist\win-unpacked\resources\app.asar\out\renderer
|
// path.join(__dirname) 根目录 E:\njys-work\AIx_Smarttalk\dist\win-unpacked\resources\app.asar\out\renderer
|
||||||
|
|
||||||
const path = require('path')
|
const isNode = typeof require !== 'undefined' // 是否支持node函数
|
||||||
const Remote = require('@electron/remote')
|
const path = isNode?require('path'):{}
|
||||||
const { ipcRenderer } = require('electron')
|
const Remote = isNode?require('@electron/remote'):{}
|
||||||
|
const { ipcRenderer } = isNode?require('electron'):window.electron || {}
|
||||||
|
|
||||||
// 常用变量
|
// 常用变量
|
||||||
const BaseUrl = process.env['ELECTRON_RENDERER_URL']+'/#'
|
const BaseUrl = isNode?process.env['ELECTRON_RENDERER_URL']+'/#':''
|
||||||
const isDev = process.env.NODE_ENV !== 'production'
|
const isDev = isNode?process.env.NODE_ENV !== 'production':''
|
||||||
|
|
||||||
|
// 暴露Remote中的属性
|
||||||
|
export const ipcMain = Remote?.ipcMain || {}
|
||||||
/**
|
/**
|
||||||
* 获取静态资源,开发和生产环境
|
* 获取静态资源,开发和生产环境
|
||||||
* @param {*} url
|
* @param {*} url
|
||||||
|
@ -39,15 +42,38 @@ export const getStaticUrl = (url = '', type = 'app', exitPath = '', isFile = fal
|
||||||
* url:路由地址,width:窗口宽度,height:窗口高度,option:自定义选项
|
* url:路由地址,width:窗口宽度,height:窗口高度,option:自定义选项
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function ipcMsgSend(key, data) {
|
export function ipcMsgSend(key, data, type) {
|
||||||
|
if (type == 'old') {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// 返回结果-监听
|
// 返回结果-监听
|
||||||
ipcRenderer.once(`${key}-reply`, (e, res) => {
|
ipcRenderer?.once(`${key}-reply`, (e, res) => {
|
||||||
resolve(res)
|
resolve(res)
|
||||||
})
|
})
|
||||||
// 发送消息
|
// 发送消息
|
||||||
ipcRenderer.send(key, data)
|
ipcRenderer?.send(key, data)
|
||||||
})
|
})
|
||||||
|
} else if (type == 'send') { // 单独发送
|
||||||
|
ipcRenderer?.send(key, data)
|
||||||
|
} else { // 新版本-默认
|
||||||
|
return ipcRenderer?.invoke(key, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function ipcMsgSend2(key, ...args) {
|
||||||
|
return ipcRenderer?.send(key, ...args)
|
||||||
|
}
|
||||||
|
export function ipcMsgInvoke(key, ...args) {
|
||||||
|
return ipcRenderer?.invoke(key, ...args)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 封装ipcRenderer事件监听
|
||||||
|
* @param {*} fn on once handle invoke
|
||||||
|
* @param {*} key
|
||||||
|
* @param {Function} cb 回调函数
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function ipcHandle(fn,key, cb) {
|
||||||
|
return ipcRenderer[fn](key, cb)
|
||||||
|
// return ipcRenderer?.[fn]?.(key, cb)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 创建-窗口 调用该方法
|
* 创建-窗口 调用该方法
|
||||||
|
@ -89,11 +115,13 @@ export const createWindow = async (type, data) => {
|
||||||
resizable: true, // 禁止窗口大小缩放
|
resizable: true, // 禁止窗口大小缩放
|
||||||
alwaysOnTop: false, // 窗口是否总是显示在其他窗口之前
|
alwaysOnTop: false, // 窗口是否总是显示在其他窗口之前
|
||||||
}
|
}
|
||||||
|
data.isConsole = true // 是否开启控制台
|
||||||
data.option = {...defOption, ...option}
|
data.option = {...defOption, ...option}
|
||||||
const win = await toolWindow(data)
|
const win = await toolWindow(data)
|
||||||
win.type = type // 唯一标识
|
win.type = type // 唯一标识
|
||||||
win.show()
|
win.show()
|
||||||
win.setFullScreen(true) // 设置窗口为全屏
|
win.setFullScreen(true) // 设置窗口为全屏
|
||||||
|
// win.webContents.openDevTools() // 打开调试工具
|
||||||
eventHandles(type, win) // 事件监听处理
|
eventHandles(type, win) // 事件监听处理
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -145,7 +173,7 @@ export function toolWindow({url, isConsole, option={}}) {
|
||||||
// 内部监听器-是否打印
|
// 内部监听器-是否打印
|
||||||
if (!!isConsole) {
|
if (!!isConsole) {
|
||||||
win.webContents.on('console-message', (e,leve,m,lin,s) => {
|
win.webContents.on('console-message', (e,leve,m,lin,s) => {
|
||||||
console.log(m)
|
console.log(`[${win.type}]`,m)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -173,13 +201,17 @@ const eventHandles = (type, win) => {
|
||||||
case 'tool-sphere': { // 创建-悬浮球
|
case 'tool-sphere': { // 创建-悬浮球
|
||||||
// 监听设置穿透
|
// 监听设置穿透
|
||||||
const setIgnore = (_, ignore) => {win.setIgnoreMouseEvents(ignore, {forward: true})}
|
const setIgnore = (_, ignore) => {win.setIgnoreMouseEvents(ignore, {forward: true})}
|
||||||
Remote.ipcMain.on('tool-sphere:set:ignore', setIgnore)
|
Remote.ipcMain.handle('tool-sphere:set:ignore', setIgnore) // 异步
|
||||||
// 关闭窗口
|
// 关闭窗口
|
||||||
Remote.ipcMain.once('tool-sphere:close', () => { win&&win.destroy() })
|
Remote.ipcMain.handleOnce('tool-sphere:close', () => {win&&win.destroy()})
|
||||||
// 放大监听-测试
|
// // 放大监听-测试
|
||||||
Remote.ipcMain.once('maximize-window', () => {win&&win.destroy()})
|
// Remote.ipcMain.once('maximize-window', () => {win&&win.destroy()})
|
||||||
const on = {
|
const on = {
|
||||||
onClosed: () => {Remote.ipcMain.off('tool-sphere:set:ignore', setIgnore)}
|
onClosed: () => {
|
||||||
|
Remote.ipcMain.removeHandler('tool-sphere:set:ignore', setIgnore)
|
||||||
|
Remote.ipcMain.removeHandler('tool-sphere:reset')
|
||||||
|
// Remote.ipcMain.removeAllListeners() // 移除所有监听事件
|
||||||
|
}
|
||||||
}
|
}
|
||||||
publicMethods(on) // 加载公共方法
|
publicMethods(on) // 加载公共方法
|
||||||
break}
|
break}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="pdfbox" ref="pdfbox">
|
<div class="pdfbox" ref="pdfbox">
|
||||||
<pdfCanvas :pdfObj="pdfObj" ref="pdfCanvaslist" @update:numPagesTotal="handleUpdate" />
|
<pdfCanvas v-if="isOnLoadShow" :pdfObj="pdfObj" ref="pdfCanvaslist" @update:numPagesTotal="handleUpdate" />
|
||||||
<div class="pdf-btn">
|
<div class="pdf-btn">
|
||||||
<el-button
|
<el-button
|
||||||
style="border-top-left-radius: 8px"
|
style="border-top-left-radius: 8px"
|
||||||
|
@ -32,20 +32,30 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch, reactive } from 'vue'
|
import { ref, onMounted, watch, reactive,watchEffect ,onBeforeUnmount} from 'vue'
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf'
|
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf'
|
||||||
import pdfCanvas from '@/components/pdf/index.vue'
|
import pdfCanvas from '@/components/pdf/index.vue'
|
||||||
import { getStaticUrl } from '@/utils/tool'
|
import { getStaticUrl } from '@/utils/tool'
|
||||||
const { ipcRenderer } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
|
import { getBookMarkById } from '@/api/eTextbook/index'
|
||||||
|
import {useToolState} from '@/store/modules/tool'
|
||||||
|
// const getStaticUrl=(url)=>{
|
||||||
|
// return url
|
||||||
|
// }
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc = getStaticUrl('/lib/build/pdf.worker.mjs')
|
pdfjsLib.GlobalWorkerOptions.workerSrc = getStaticUrl('/lib/build/pdf.worker.mjs')
|
||||||
|
const toolState = useToolState();
|
||||||
|
const route = useRoute();
|
||||||
|
const isOnLoadShow = ref(false) //加载完毕显示
|
||||||
// 传过去的参数
|
// 传过去的参数
|
||||||
const pdfObj = reactive({
|
const pdfObj = reactive({
|
||||||
numberOfPdf: 2, //显示几页
|
numberOfPdf: 2, //显示几页
|
||||||
pdfUrl: getStaticUrl('aaa.pdf', 'user', 'selfFile', true),
|
pdfUrl: getStaticUrl('aaa.pdf', 'user', 'selfFile', true),
|
||||||
|
allPageData:[],
|
||||||
|
bookId:null,
|
||||||
numPages: 1 //当前页数
|
numPages: 1 //当前页数
|
||||||
})
|
})
|
||||||
|
const textbookId=ref(null) //书籍id
|
||||||
// 总条数
|
// 总条数
|
||||||
const numPagesTotal = ref(0)
|
const numPagesTotal = ref(0)
|
||||||
const pdfCanvaslist = ref(null)
|
const pdfCanvaslist = ref(null)
|
||||||
|
@ -60,17 +70,22 @@ const navtopage = (type) => {
|
||||||
pdfObj.numPages += num
|
pdfObj.numPages += num
|
||||||
}
|
}
|
||||||
if (pdfObj.numPages > numPagesTotal.value) return
|
if (pdfObj.numPages > numPagesTotal.value) return
|
||||||
pdfCanvaslist.value.initPdf()
|
pdfCanvaslist.value.initPdf('rest')
|
||||||
}
|
}
|
||||||
// 最小化窗口
|
// 最小化窗口
|
||||||
const minimize = () => {
|
const minimize = async () => {
|
||||||
ipcRenderer.send('open-PDF:minimize')
|
await pdfCanvaslist.value.savaDataStore()
|
||||||
|
// toolState.isPdfWin=false
|
||||||
|
// toolState.showBoardAll=true //恢复默认值
|
||||||
|
// console.log(toolState.showBoardAll,"关闭")
|
||||||
|
// // ipcRenderer.send('tool-sphere:reset') //重置tool状态
|
||||||
|
// ipcRenderer.send('open-PDF:minimize')
|
||||||
}
|
}
|
||||||
const handleUpdate = (data) => {
|
const handleUpdate = (data) => {
|
||||||
numPagesTotal.value = data
|
numPagesTotal.value = data
|
||||||
if (numPagesTotal.value == 1) {
|
if (numPagesTotal.value == 1) {
|
||||||
pdfObj.numberOfPdf = 1
|
pdfObj.numberOfPdf = 1
|
||||||
pdfCanvaslist.value.initPdf('restone')
|
pdfCanvaslist.value.initPdf('rest')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 单双页切换
|
// 单双页切换
|
||||||
|
@ -87,10 +102,35 @@ const switchPageMode = () => {
|
||||||
} else {
|
} else {
|
||||||
// 多页切单页
|
// 多页切单页
|
||||||
pdfObj.numberOfPdf = 1
|
pdfObj.numberOfPdf = 1
|
||||||
pdfCanvaslist.value.initPdf('restone')
|
pdfCanvaslist.value.initPdf('rest')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMounted(async () => {})
|
onMounted(async () => {
|
||||||
|
toolState.isPdfWin=true
|
||||||
|
console.log(toolState.showBoardAll,"c初始")
|
||||||
|
textbookId.value = route.query.textbookId
|
||||||
|
pdfObj.bookId=textbookId.value
|
||||||
|
getBookMarkById(textbookId.value).then(res=>{
|
||||||
|
pdfObj.allPageData=getUniqueArrayByLastOccurrence(res.data)
|
||||||
|
isOnLoadShow.value=true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//根据page去重
|
||||||
|
const getUniqueArrayByLastOccurrence=(array)=> {
|
||||||
|
const uniqueItems = array.reduce((acc, current) => {
|
||||||
|
// 使用 Map 来跟踪最后一个出现的 pageNum 和它的对象
|
||||||
|
acc.set(current.pageNum, current);
|
||||||
|
return acc;
|
||||||
|
}, new Map());
|
||||||
|
|
||||||
|
// 将 Map 的值转换回数组
|
||||||
|
const resultArray = Array.from(uniqueItems.values());
|
||||||
|
|
||||||
|
return resultArray;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref,defineProps,defineEmits} from "vue";
|
import {ref} from "vue";
|
||||||
const activeIndex = ref('0')
|
const activeIndex = ref('0')
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
classList:{
|
classList:{
|
||||||
|
|
|
@ -115,6 +115,7 @@ import uploadDialog from '@/components/upload-dialog/index.vue'
|
||||||
import { Refresh } from '@element-plus/icons-vue'
|
import { Refresh } from '@element-plus/icons-vue'
|
||||||
import uploaderState from '@/store/modules/uploader'
|
import uploaderState from '@/store/modules/uploader'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import { useToolState } from '@/store/modules/tool'
|
||||||
import MoveFile from '@/components/move-file/index.vue'
|
import MoveFile from '@/components/move-file/index.vue'
|
||||||
import FileListItem from '@/views/prepare/container/file-list-item.vue'
|
import FileListItem from '@/views/prepare/container/file-list-item.vue'
|
||||||
import { getSmarttalkPage, moveSmarttalk } from '@/api/file'
|
import { getSmarttalkPage, moveSmarttalk } from '@/api/file'
|
||||||
|
@ -534,18 +535,23 @@ export default {
|
||||||
|
|
||||||
// 打开PDF-课件
|
// 打开PDF-课件
|
||||||
async navtoPdf() {
|
async navtoPdf() {
|
||||||
let path = await this.getBookPathFromServer()
|
const toolStore = useToolState()
|
||||||
console.log(path)
|
if (toolStore.isPdfWin) return this.$message.error('您当前已打开课本,请勿重复操作')
|
||||||
createWindow('open-PDF', { url: '/classBegins/index' })
|
// let path = await this.getBookPathFromServer()
|
||||||
|
// console.log(path)
|
||||||
|
// console.log(this.uploadData.textbookId)
|
||||||
|
createWindow('open-PDF', { url: '/classBegins/index?textbookId='+this.uploadData.textbookId })
|
||||||
},
|
},
|
||||||
// 上课-工具类悬浮
|
// 上课-工具类悬浮
|
||||||
openLesson() {
|
openLesson() {
|
||||||
|
const toolStore = useToolState()
|
||||||
|
if (toolStore.isToolWin) return this.$message.error('您当前已开始上课,请勿重复操作')
|
||||||
createWindow('tool-sphere', { url: '/tool/sphere' })
|
createWindow('tool-sphere', { url: '/tool/sphere' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style lang="scss">
|
||||||
.prepare-popper {
|
.prepare-popper {
|
||||||
width: 80px !important;
|
width: 80px !important;
|
||||||
min-width: 80px !important;
|
min-width: 80px !important;
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
// 功能说明:画板
|
// 功能说明:画板
|
||||||
import { ref, onMounted, watch } from 'vue'
|
import { ref, onMounted, watch,defineExpose } from 'vue'
|
||||||
import {FabricVue, TYPES} from '@/plugins/fabric'
|
import {FabricVue, TYPES} from '@/plugins/fabric'
|
||||||
|
import { useToolState } from '@/store/modules/tool'
|
||||||
|
const toolStore = useToolState()
|
||||||
const canvasRef = ref(null) // 画布
|
const canvasRef = ref(null) // 画布
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: String
|
modelValue: String
|
||||||
|
@ -23,10 +25,13 @@ onMounted(async() => {
|
||||||
await FabricVue.initCanvas(canvasRef.value, option)
|
await FabricVue.initCanvas(canvasRef.value, option)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const handleMode = (newVal, oldVal) => {
|
||||||
// 监听
|
if(toolStore.isPdfWin){
|
||||||
watch(() => props.modelValue, (newVal, oldVal) => {
|
if(newVal=='clear'){
|
||||||
// console.log(newVal, oldVal)
|
emit('update:modelValue', oldVal)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
switch(newVal) {
|
switch(newVal) {
|
||||||
case 'select': // 选择模式
|
case 'select': // 选择模式
|
||||||
FabricVue.handleMode(TYPES.ActionMode.OTHER)
|
FabricVue.handleMode(TYPES.ActionMode.OTHER)
|
||||||
|
@ -35,14 +40,26 @@ watch(() => props.modelValue, (newVal, oldVal) => {
|
||||||
FabricVue.handleMode(TYPES.ActionMode.DRAW)
|
FabricVue.handleMode(TYPES.ActionMode.DRAW)
|
||||||
FabricVue.canvas.freeDrawingCursor = 'default'
|
FabricVue.canvas.freeDrawingCursor = 'default'
|
||||||
break
|
break
|
||||||
case 'eraser': // 板擦模式
|
case 'erase': // 板擦模式
|
||||||
FabricVue.handleMode(TYPES.ActionMode.ERASE)
|
FabricVue.handleMode(TYPES.ActionMode.ERASE)
|
||||||
break
|
break
|
||||||
case 'clear': // 清空画布
|
case 'clear': // 清空画布
|
||||||
|
if(oldVal){
|
||||||
FabricVue.history?.clean()
|
FabricVue.history?.clean()
|
||||||
emit('update:modelValue', oldVal)
|
emit('update:modelValue', oldVal)
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// 监听
|
||||||
|
watch(() => props.modelValue, (newVal, oldVal) => {
|
||||||
|
// console.log(newVal, oldVal)
|
||||||
|
handleMode(newVal, oldVal)
|
||||||
|
})
|
||||||
|
// 暴露属性方法
|
||||||
|
defineExpose({
|
||||||
|
handleMode
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
<template>
|
||||||
|
<div class="warp" ref="btnRef">
|
||||||
|
<slot name="start"></slot>
|
||||||
|
<!-- 工具按钮 -->
|
||||||
|
<el-space direction="vertical">
|
||||||
|
<template v-for="(item,index) in list">
|
||||||
|
<slot :name="item.prop" :item="item" :index="index">
|
||||||
|
<div class="c-btn flex flex-col items-center gap-2 p-2" @click.stop="clickHandel(item,$event)">
|
||||||
|
<i class="iconfont" :class="item.icon" :style="item.style" />
|
||||||
|
<span>{{item.label||item.text||item.name}}</span>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
<slot name="append"></slot>
|
||||||
|
</el-space>
|
||||||
|
<slot name="end"></slot>
|
||||||
|
<!-- 内容部分 -->
|
||||||
|
<transition name="el-fade-in">
|
||||||
|
<div class="c-popover" :style="`--top: ${topPos}px;--height:${hPost}px;`" v-show="isVisible">
|
||||||
|
<div class="content">{{activeObj}}</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { computed, defineProps, ref, reactive, watchEffect, onMounted } from 'vue'
|
||||||
|
// 功能说明:侧边-工具栏
|
||||||
|
const colors = ['#00f389', '#ff7f00', '#ffff00', '#409EFF', '#00baff', '#13b189', '#F56C6C']
|
||||||
|
const emit = defineEmits(['update:modelValue','change'])
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: { // 是否显示
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
data: { // 数据
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ label: '资源', prop: 'resource', icon: 'icon-kechengziyuan1' },
|
||||||
|
{ label: '互动', prop: 'interact', icon: 'icon-hudong' },
|
||||||
|
{ label: '窗口', prop: 'win', icon: 'icon-tubiaozhizuomobanyihuifu-' },
|
||||||
|
{ label: '下课', prop: 'over', isExtra: true, icon: 'icon-a-lujing13357' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const isVisible = ref(false) // 是否显示内容
|
||||||
|
const activeObj = ref(null) // 当前激活的按钮
|
||||||
|
const btnRef = ref(null) // 按钮元素-ref
|
||||||
|
const topPos = ref(30) // 顶部距离-内容的距离
|
||||||
|
const hPost = ref(0) // 顶部距离-内容的距离
|
||||||
|
let posBtnAll = {} // 存储位置
|
||||||
|
// === 计算属性 ===
|
||||||
|
const list = computed(() => props.data.map((o,i) => {
|
||||||
|
o.style = getStyle(o.style, i)
|
||||||
|
return o
|
||||||
|
}))
|
||||||
|
onMounted(() => {
|
||||||
|
posBtnAll = btnRef.value.getBoundingClientRect()
|
||||||
|
hPost.value = posBtnAll.height
|
||||||
|
})
|
||||||
|
// === 方法 ===
|
||||||
|
// 获取颜色索引
|
||||||
|
const getIndex = i => i % colors.length
|
||||||
|
// 获取样式
|
||||||
|
const getStyle = (style,index) => {
|
||||||
|
const color = colors[getIndex(index)]
|
||||||
|
if (!style) return {color}
|
||||||
|
else {
|
||||||
|
if (typeof style === 'object') return {...style, color}
|
||||||
|
return `${style}${style.endsWith(';')?'':';'}color:${color};`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 事件
|
||||||
|
const clickHandel = (o, e) => {
|
||||||
|
if (!o.isExtra) { // 忽略其他操作: 打开内容窗口,指示器指向当前
|
||||||
|
const node = e.target.parentNode.getBoundingClientRect()
|
||||||
|
const isColse = activeObj.value && activeObj.value.prop === o.prop && isVisible.value
|
||||||
|
isVisible.value = !isColse // 相同的按钮且打开状态,点击关闭
|
||||||
|
activeObj.value = o
|
||||||
|
const nodeH = parseInt(node.height / 2) // 高度的一半
|
||||||
|
topPos.value = parseInt(node.top) - posBtnAll.top + nodeH
|
||||||
|
}
|
||||||
|
emit('change', o)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.warp{
|
||||||
|
border: 1px solid;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
right: 10px;
|
||||||
|
min-height: 40vh;
|
||||||
|
min-width: 4em;
|
||||||
|
border-radius: 4em;
|
||||||
|
background-color: #121212;
|
||||||
|
.el-space{margin: 20px 0;}
|
||||||
|
.c-btn{
|
||||||
|
color: #d9dce3;
|
||||||
|
cursor: pointer;
|
||||||
|
.iconfont{
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
span{font-size: 12px;}
|
||||||
|
&:hover{
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #454545fa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.c-popover{
|
||||||
|
--top: 30px;
|
||||||
|
--height: 40vh;
|
||||||
|
position: fixed;
|
||||||
|
inset: 50% 75px auto auto;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
background-color: #121212;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
min-height: var(--height);
|
||||||
|
width: 30em;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&:before{
|
||||||
|
content: "";
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: #121212;
|
||||||
|
position: absolute;
|
||||||
|
right: -5px;
|
||||||
|
top: var(--top);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
color: red;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* 处理元素是否穿透-窗口
|
||||||
|
*/
|
||||||
|
import { ipcMsgSend } from '@/utils/tool'
|
||||||
|
class Ignore {
|
||||||
|
el // 绑定元素
|
||||||
|
binding // 绑定对象(参数)
|
||||||
|
value // 绑定值
|
||||||
|
isAuto // 是否自动控制
|
||||||
|
constructor(el, binding) {
|
||||||
|
this.el = el
|
||||||
|
this.binding = binding
|
||||||
|
this.value = binding.value
|
||||||
|
this.isAuto = !(this.value && this.value instanceof Boolean)
|
||||||
|
}
|
||||||
|
// 设置是否穿透
|
||||||
|
send(bool) {
|
||||||
|
ipcMsgSend('tool-sphere:set:ignore', bool)
|
||||||
|
}
|
||||||
|
// 监听元素移入移出,自动设置
|
||||||
|
mounted() {
|
||||||
|
this.el.addEventListener('mouseenter', e => { // 进入
|
||||||
|
this.send(false) // 元素不穿透,鼠标有效
|
||||||
|
this.changeHandle(e)
|
||||||
|
})
|
||||||
|
this.el.addEventListener('mouseleave', e => { // 离开
|
||||||
|
this.send(true) // 元素穿透,鼠标无效
|
||||||
|
this.changeHandle(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
changeHandle(e) {
|
||||||
|
const data = {detail:{ignore: this, e, type: e.type}}
|
||||||
|
const customEvent = new CustomEvent('ignore-mounted', data)
|
||||||
|
this.el.dispatchEvent(customEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
mounted(el, binding) {
|
||||||
|
const ignore = new Ignore(el, binding)
|
||||||
|
if (ignore.isAuto) { // 自动控制
|
||||||
|
ignore.mounted()
|
||||||
|
} else { // 手动设置
|
||||||
|
ignore.send(ignore.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="warp-all">
|
<div class="warp-all">
|
||||||
<board-vue v-model="tabActive" v-show="isShow"></board-vue>
|
<!-- 画板 -->
|
||||||
|
<board-vue v-model="tabActive" v-show="isShow" ref="boardVueRef"></board-vue>
|
||||||
|
<!-- 侧边工具栏 -->
|
||||||
|
<side-vue v-ignore @ignore-mounted="sideMouse" @change="sideChange"></side-vue>
|
||||||
<!-- 底部工具栏 :style="dataPos.style"-->
|
<!-- 底部工具栏 :style="dataPos.style"-->
|
||||||
<div class="tool-bottom-all"
|
<div class="tool-bottom-all" @mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
|
||||||
@mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
|
|
||||||
<div v-drag="{handle:'.tool-bottom-all', dragtime}"
|
<div v-drag="{handle:'.tool-bottom-all', dragtime}"
|
||||||
@v-drag-start="dragtime = Date.now()">
|
@v-drag-start="dragtime = Date.now()">
|
||||||
<div class="c-logo" @click="logoHandle" title="拖动 | 折叠 | 展开">
|
<div class="c-logo" @click="logoHandle" title="拖动 | 折叠 | 展开">
|
||||||
|
@ -15,7 +17,7 @@
|
||||||
@change="tabChange">
|
@change="tabChange">
|
||||||
<template #default="{item}">
|
<template #default="{item}">
|
||||||
<div class="c-btn flex flex-col items-center gap-2 p-2">
|
<div class="c-btn flex flex-col items-center gap-2 p-2">
|
||||||
<i class="iconfont" :class="item.icon" :style="item.style"></i>
|
<i class="iconfont" :class="item.icon" :style="item.style" />
|
||||||
<span>{{item.label}}</span>
|
<span>{{item.label}}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -29,70 +31,96 @@
|
||||||
// 功能说明:electron 悬浮球
|
// 功能说明:electron 悬浮球
|
||||||
import { onMounted, ref, reactive, watchEffect } from 'vue'
|
import { onMounted, ref, reactive, watchEffect } from 'vue'
|
||||||
import logo from '@root/resources/icon.png' // logo
|
import logo from '@root/resources/icon.png' // logo
|
||||||
import boardVue from './components/board.vue' // 画板
|
import boardVue from './components/board.vue' // 画板-子组件
|
||||||
|
import sideVue from './components/side.vue' // 画板-子组件
|
||||||
import vDrag from './directive/drag' // 自定义指令-拖拽
|
import vDrag from './directive/drag' // 自定义指令-拖拽
|
||||||
|
import vIgnore from './directive/ignore' // 自定义指令-穿透
|
||||||
import { useToolState } from '@/store/modules/tool'
|
import { useToolState } from '@/store/modules/tool'
|
||||||
const { ipcRenderer } = require('electron') // app使用
|
import { ipcMsgSend, ipcHandle, ipcMain, ipcMsgInvoke } from '@/utils/tool' // 相关工具
|
||||||
// const ipcRenderer = { send: () => {} } // 网页测试使用
|
|
||||||
|
|
||||||
const tabActive = ref('select') // 工具栏当前选中项
|
const tabActive = ref('select') // 工具栏当前选中项
|
||||||
const isFold = ref(false) // 折叠工具栏
|
const isFold = ref(false) // 折叠工具栏
|
||||||
const isDrag = ref(false) // 开始拖拽
|
const isDrag = ref(false) // 开始拖拽
|
||||||
const dragtime = ref(0) // 拖拽时间-计算点击还是拖动
|
const dragtime = ref(0) // 拖拽时间-计算点击还是拖动
|
||||||
const isShow = ref(false)
|
const isShow = ref(false) // 是否显示-画板
|
||||||
const toolStore = useToolState()
|
const toolStore = useToolState() // 状态管理
|
||||||
|
const boardVueRef=ref(null) // 画板ref
|
||||||
const btnList = [ // 工具栏按钮列表
|
const btnList = [ // 工具栏按钮列表
|
||||||
{ label: '选择', value: 'select', icon: 'icon-mouse' },
|
{ label: '选择', value: 'select', icon: 'icon-mouse' },
|
||||||
{ label: '画笔', value: 'brush', icon: 'icon-huabi' },
|
{ label: '画笔', value: 'brush', icon: 'icon-huabi' },
|
||||||
{ label: '板擦', value: 'eraser', icon: 'icon-xiangpica' },
|
{ label: '板擦', value: 'erase', icon: 'icon-xiangpica' },
|
||||||
{ label: '清除', value: 'clear', icon: 'icon-xiangpica', style: 'color: #ccc' },
|
{ label: '清除', value: 'clear', icon: 'icon-xiangpica', style: 'color: #ccc' },
|
||||||
// { label: '互动', value: 'interact', icon: 'icon-hudong' },
|
// { label: '互动', value: 'interact', icon: 'icon-hudong' },
|
||||||
// { label: '聚焦', value: 'focus', icon: 'icon-jujiao' },
|
// { label: '聚焦', value: 'focus', icon: 'icon-jujiao' },
|
||||||
// { label: '更多', value: 'more', icon: 'icon-xiazai9' },
|
// { label: '更多', value: 'more', icon: 'icon-xiazai9' },
|
||||||
]
|
]
|
||||||
onMounted(() => {
|
// === 页面加载完毕 ===
|
||||||
// isShow.value = toolStore.showBoardAll // 是否显示-画板
|
onMounted(async() => {
|
||||||
// console.log('xxx: ', toolStore.model)
|
resetStatus() // 开启重置状态-监听
|
||||||
// setTimeout(() => {
|
|
||||||
// toolStore.windowState.test = '测试成功'
|
|
||||||
// }, 2000);
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// ==== 方法 ===
|
// ==== 方法 ===
|
||||||
const tabChange = (val) => { // 切换tab-change
|
// const test = (e) => { console.log('test', e) }
|
||||||
// console.log('xxxx:', val)
|
// 切换tab-change
|
||||||
toolStore.showBoardAll = true
|
const tabChange = (val) => {
|
||||||
switch (val) {
|
const bool = !toolStore.isPdfWin && !toolStore.showBoardAll
|
||||||
case 'brush': // 画笔
|
if(bool) toolStore.showBoardAll = true
|
||||||
break
|
// ipcMsgSend('tool-sphere:close')
|
||||||
case 'eraser': // 板擦
|
|
||||||
break
|
|
||||||
case 'interact':
|
|
||||||
break
|
|
||||||
case 'focus':
|
|
||||||
break
|
|
||||||
case 'more':
|
|
||||||
break
|
|
||||||
case 'close':
|
|
||||||
ipcRenderer.send('tool-sphere:close')
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
toolStore.model = val // 存储当前tab
|
toolStore.model = val // 存储当前tab
|
||||||
}
|
}
|
||||||
const logoHandle = (e,t) => { // logo 点击-事件 折叠|展开
|
// logo 点击-事件 折叠|展开
|
||||||
|
const logoHandle = (e,t) => {
|
||||||
if (Date.now() - dragtime.value < 200) {
|
if (Date.now() - dragtime.value < 200) {
|
||||||
isFold.value = !isFold.value
|
isFold.value = !isFold.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 底部工具栏:移入移出-是否穿透
|
||||||
const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
const mouseChange = (bool) => {
|
||||||
let resBool = false
|
let resBool = false
|
||||||
if (tabActive.value == 'select') resBool = !!bool
|
if (tabActive.value == 'select') resBool = !!bool
|
||||||
ipcRenderer.send('tool-sphere:set:ignore', resBool)
|
if (!isShow.value) resBool = !!bool
|
||||||
|
setIgnore(resBool)
|
||||||
}
|
}
|
||||||
watchEffect(() => { // 监听
|
// 忽略鼠标穿透
|
||||||
isShow.value = toolStore.showBoardAll // 是否显示-画板
|
const setIgnore = (bool) => {ipcMsgSend('tool-sphere:set:ignore', bool)}
|
||||||
|
// 重置状态: 鼠标|画板
|
||||||
|
const resetStatus = () => {
|
||||||
|
if (toolStore.isToolWin) return // 已经打开过-忽略
|
||||||
|
ipcMain?.handle?.('tool-sphere:reset', () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
boardVueRef.value.handleMode(tabActive.value)
|
||||||
|
mouseChange(1)
|
||||||
|
}, 500)
|
||||||
|
})
|
||||||
|
toolStore.isToolWin = true // 标记状态
|
||||||
|
}
|
||||||
|
// 侧边工具栏: 移入移出
|
||||||
|
const sideMouse = e => {
|
||||||
|
const {type} = e.detail
|
||||||
|
mouseChange(type == 'mouseleave')
|
||||||
|
}
|
||||||
|
// 侧边工具栏: 操作变化
|
||||||
|
const sideChange = o => {
|
||||||
|
// console.log(o)
|
||||||
|
switch(o.prop) {
|
||||||
|
case 'resource': // 资源
|
||||||
|
break
|
||||||
|
case 'interact': // 互动
|
||||||
|
break
|
||||||
|
case 'win': // 窗口
|
||||||
|
break
|
||||||
|
case 'over': // 下课
|
||||||
|
toolStore.isToolWin = false
|
||||||
|
ipcMsgSend('tool-sphere:close')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 监听器 ===
|
||||||
|
watchEffect(() => {
|
||||||
|
// 不同的时候, 更新值: 是否显示-画板
|
||||||
|
const show = !toolStore.isPdfWin && toolStore.showBoardAll
|
||||||
|
if (show != isShow.value) isShow.value = show
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -118,6 +146,7 @@ watchEffect(() => { // 监听
|
||||||
height: 5rem;
|
height: 5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
box-shadow: 0px 0px 8px rgb(0 0 0 / 40%);
|
box-shadow: 0px 0px 8px rgb(0 0 0 / 40%);
|
||||||
|
user-select: none;
|
||||||
// &:hover{
|
// &:hover{
|
||||||
// .el-image{transform: scale(1.1);}
|
// .el-image{transform: scale(1.1);}
|
||||||
// }
|
// }
|
||||||
|
|
Loading…
Reference in New Issue