@airhang/vue-book-reader 1.0.0

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.
@@ -0,0 +1,3389 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory();
4
+ else if(typeof define === 'function' && define.amd)
5
+ define([], factory);
6
+ else if(typeof exports === 'object')
7
+ exports["vue-book-reader"] = factory();
8
+ else
9
+ root["vue-book-reader"] = factory();
10
+ })((typeof self !== 'undefined' ? self : this), function() {
11
+ return /******/ (function() { // webpackBootstrap
12
+ /******/ "use strict";
13
+ /******/ // The require scope
14
+ /******/ var __webpack_require__ = {};
15
+ /******/
16
+ /************************************************************************/
17
+ /******/ /* webpack/runtime/define property getters */
18
+ /******/ !function() {
19
+ /******/ // define getter functions for harmony exports
20
+ /******/ __webpack_require__.d = function(exports, definition) {
21
+ /******/ for(var key in definition) {
22
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
23
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
24
+ /******/ }
25
+ /******/ }
26
+ /******/ };
27
+ /******/ }();
28
+ /******/
29
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
30
+ /******/ !function() {
31
+ /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
32
+ /******/ }();
33
+ /******/
34
+ /******/ /* webpack/runtime/make namespace object */
35
+ /******/ !function() {
36
+ /******/ // define __esModule on exports
37
+ /******/ __webpack_require__.r = function(exports) {
38
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
39
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
40
+ /******/ }
41
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
42
+ /******/ };
43
+ /******/ }();
44
+ /******/
45
+ /******/ /* webpack/runtime/publicPath */
46
+ /******/ !function() {
47
+ /******/ __webpack_require__.p = "";
48
+ /******/ }();
49
+ /******/
50
+ /************************************************************************/
51
+ var __webpack_exports__ = {};
52
+ // ESM COMPAT FLAG
53
+ __webpack_require__.r(__webpack_exports__);
54
+
55
+ // EXPORTS
56
+ __webpack_require__.d(__webpack_exports__, {
57
+ BookCatalogueDrawer: function() { return /* reexport */ BookCatalogueDrawer; },
58
+ BookReader: function() { return /* reexport */ BookReader; },
59
+ "default": function() { return /* binding */ entry_lib; }
60
+ });
61
+
62
+ ;// ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
63
+ /* eslint-disable no-var */
64
+ // This file is imported into lib/wc client bundles.
65
+
66
+ if (typeof window !== 'undefined') {
67
+ var currentScript = window.document.currentScript
68
+ if (false) // removed by dead control flow
69
+ { var getCurrentScript; }
70
+
71
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
72
+ if (src) {
73
+ __webpack_require__.p = src[1] // eslint-disable-line
74
+ }
75
+ }
76
+
77
+ // Indicate to webpack that this file can be concatenated
78
+ /* harmony default export */ var setPublicPath = (null);
79
+
80
+ ;// ./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/BookReader.vue?vue&type=template&id=eaca7004&scoped=true
81
+ var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:"photo-album-container",style:({ transform: `scale(${_vm.zoomScale}) translate(${_vm.translateX}px, ${_vm.translateY}px)` }),on:{"touchstart":_vm.onContainerTouchStart,"touchmove":_vm.onContainerTouchMove,"touchend":_vm.onContainerTouchEnd,"dblclick":_vm.onContainerDoubleClick,"click":_vm.onContentClick}},[( false)?0:_vm._e(),(_vm.contentReady)?_c('div',{staticClass:"flipbook-wrapper",on:{"dblclick":_vm.onFlipbookDoubleClick,"!touchstart":function($event){return _vm.onFlipbookTouchStart.apply(null, arguments)},"!touchend":function($event){return _vm.onFlipbookTouchEnd.apply(null, arguments)}}},[(_vm.flipMode === 'flip' && _vm.flag)?_c('flipbook',{ref:"flipbook",class:['flipbook', _vm.isMobile ? 'mobile-mode mobile-optimized' : 'desktop-mode desktop-optimized'],attrs:{"pages":_vm.pages,"pagesHiRes":_vm.pagesHiRes,"startPage":_vm.startPage,"zooms":null,"ambient-light":0.6,"gloss":0.4,"single-page":_vm.isMobile,"click-to-flip":false,"wheel-to-flip":!_vm.isMobile,"swipe-to-flip":true,"center-pages":true},on:{"flip-left-end":_vm.onFlipLeftEnd,"flip-right-end":_vm.onFlipRightEnd},scopedSlots:_vm._u([{key:"default",fn:function({ page, canFlipLeft, canFlipRight }){return undefined}}],null,false,2449366912)}):(_vm.flipMode === 'slide')?_c('div',{ref:"slideViewer",class:['slide-viewer', _vm.isMobile ? 'mobile-mode mobile-optimized' : 'desktop-mode desktop-optimized'],on:{"touchstart":_vm.onSlideViewerTouchStart,"touchmove":_vm.onSlideViewerTouchMove,"touchend":_vm.onSlideViewerTouchEnd}},[_c('div',{staticClass:"slide-container",style:(_vm.slideContainerStyle)},_vm._l((_vm.pages),function(page,index){return _c('div',{key:index,staticClass:"slide-page",class:{ 'slide-page-active': index + 1 === _vm.currentPage }},[(page)?_c('img',{staticClass:"slide-page-image",attrs:{"src":page,"alt":""}}):_c('div',{staticClass:"slide-page-placeholder"},[_vm._v("封面/封底")])])}),0)]):(_vm.flipMode === 'fade')?_c('div',{ref:"fadeViewer",class:['fade-viewer', _vm.isMobile ? 'mobile-mode mobile-optimized' : 'desktop-mode desktop-optimized']},[_c('transition',{attrs:{"name":"fade-page","mode":"out-in"}},[_c('div',{key:_vm.currentPage,staticClass:"fade-page-container"},[(_vm.pages[_vm.currentPage - 1])?_c('img',{staticClass:"fade-page-image",attrs:{"src":_vm.pages[_vm.currentPage - 1],"alt":""}}):_c('div',{staticClass:"fade-page-placeholder"},[_vm._v("封面/封底")])])])],1):(_vm.flipMode === 'scroll')?_c('div',{ref:"scrollViewer",class:['scroll-viewer', _vm.isMobile ? 'mobile-mode mobile-optimized' : 'desktop-mode desktop-optimized'],on:{"scroll":_vm.onScrollViewerScroll}},[_c('div',{staticClass:"scroll-container"},_vm._l((_vm.pages),function(page,index){return _c('div',{key:index,ref:'scrollPage' + index,refInFor:true,staticClass:"scroll-page"},[(page)?_c('img',{staticClass:"scroll-page-image",attrs:{"src":page,"alt":""}}):_c('div',{staticClass:"scroll-page-placeholder"},[_vm._v("封面/封底")])])}),0)]):(_vm.flipMode === 'clip')?_c('div',{ref:"clipViewer",class:['clip-viewer', _vm.isMobile ? 'mobile-mode mobile-optimized' : 'desktop-mode desktop-optimized']},[_c('div',{staticClass:"clip-pages-wrapper"},[_c('transition',{attrs:{"name":"clip-current"}},[_c('div',{key:'current-' + _vm.currentPage,staticClass:"clip-page clip-page-current"},[(_vm.pages[_vm.currentPage - 1])?_c('img',{staticClass:"clip-page-image",attrs:{"src":_vm.pages[_vm.currentPage - 1],"alt":""}}):_c('div',{staticClass:"clip-page-placeholder"},[_vm._v("封面/封底")])])]),(_vm.currentPage < _vm.totalPages)?_c('div',{staticClass:"clip-page clip-page-next"},[(_vm.pages[_vm.currentPage])?_c('img',{staticClass:"clip-page-image",attrs:{"src":_vm.pages[_vm.currentPage],"alt":""}}):_c('div',{staticClass:"clip-page-placeholder"},[_vm._v("封面/封底")])]):_vm._e()],1)]):(_vm.flipMode === 'card')?_c('div',{ref:"cardViewer",class:['card-viewer', _vm.isMobile ? 'mobile-mode mobile-optimized' : 'desktop-mode desktop-optimized']},[_c('div',{staticClass:"card-stack"},[_c('transition-group',{staticClass:"card-transition-group",attrs:{"name":"card-flip","tag":"div"}},_vm._l((_vm.visibleCards),function(page,index){return _c('div',{key:'card-' + page.originalIndex,staticClass:"card-item",class:{
82
+ 'card-item-prev': page.position === 'prev',
83
+ 'card-item-current': page.position === 'current',
84
+ 'card-item-next': page.position === 'next'
85
+ },style:(_vm.getCardStyle(page.position))},[_c('div',{staticClass:"card-content"},[(page.src)?_c('img',{staticClass:"card-image",attrs:{"src":page.src,"alt":""}}):_c('div',{staticClass:"card-placeholder"},[_vm._v("封面/封底")])]),_c('div',{staticClass:"card-page-number"},[_vm._v(_vm._s(page.originalIndex + 1)+" / "+_vm._s(_vm.totalPages))])])}),0)],1)]):_vm._e()],1):_vm._e(),_c('div',{staticClass:"controls",class:{ 'mobile-controls': _vm.isMobile, 'desktop-controls': !_vm.isMobile, 'controls-visible': _vm.showControls },on:{"click":function($event){$event.stopPropagation();}}},[_c('button',{staticClass:"btn btn-prev",on:{"click":_vm.flipLeft}},[_vm._v(" ← 上一页 ")]),_c('span',{staticClass:"page-indicator"},[(_vm.totalPages === 0)?_c('span',[_vm._v("加载中...")]):(_vm.currentPage === 1 && _vm.totalPages > 1)?_c('span',[_vm._v("封面")]):(_vm.currentPage === _vm.totalPages && _vm.totalPages > 1)?_c('span',[_vm._v("封底")]):(!_vm.isMobile && _vm.totalPages > 2)?_c('span',[_vm._v("第 "+_vm._s(Math.ceil((_vm.currentPage - 1) / 2))+" 组 / 共 "+_vm._s(Math.ceil((_vm.totalPages - 2) / 2))+" 组")]):(_vm.isMobile && _vm.totalPages > 2)?_c('span',[_vm._v("第 "+_vm._s(Math.max(1, _vm.currentPage ))+" 页 / 共 "+_vm._s(Math.max(0, _vm.totalPages - 2))+" 页")]):(_vm.totalPages === 1)?_c('span',[_vm._v("第 1 页 / 共 1 页")]):_c('span',[_vm._v("第 "+_vm._s(_vm.currentPage)+" 页 / 共 "+_vm._s(_vm.totalPages)+" 页")])]),_c('button',{staticClass:"btn btn-next",on:{"click":_vm.flipRight}},[_vm._v(" 下一页 → ")])]),(_vm.showFlipModeSelector)?_c('div',{staticClass:"flip-mode-selector",class:{ 'mobile-flip-mode-selector': _vm.isMobile }},[_c('button',{staticClass:"btn btn-flip-mode",on:{"click":_vm.toggleFlipModeMenu}},[_c('span',{staticClass:"flip-mode-icon"},[_vm._v(_vm._s(_vm.flipModeIcon))]),_c('span',{staticClass:"flip-mode-text"},[_vm._v(_vm._s(_vm.flipModeLabel))])]),(_vm.showFlipModeMenu)?_c('div',{staticClass:"flip-mode-menu"},_vm._l((_vm.flipModes),function(mode){return _c('div',{key:mode.value,staticClass:"flip-mode-item",class:{ 'flip-mode-item-active': _vm.flipMode === mode.value },on:{"click":function($event){return _vm.selectFlipMode(mode.value)}}},[_c('span',{staticClass:"flip-mode-item-icon"},[_vm._v(_vm._s(mode.icon))]),_c('span',{staticClass:"flip-mode-item-label"},[_vm._v(_vm._s(mode.label))])])}),0):_vm._e()]):_vm._e(),_c('div',{staticClass:"catalogue-button",class:{
86
+ 'mobile-catalogue-button': _vm.isMobile,
87
+ 'dragging': _vm.catalogueButtonDragging,
88
+ 'catalogue-visible': _vm.showControls
89
+ },style:({
90
+ left: _vm.catalogueButtonPosition.x + 'px',
91
+ top: _vm.catalogueButtonPosition.y + 'px'
92
+ }),on:{"mousedown":_vm.onCatalogueMouseDown,"touchstart":_vm.onCatalogueTouchStart,"touchmove":_vm.onCatalogueTouchMove,"touchend":_vm.onCatalogueTouchEnd,"click":function($event){$event.stopPropagation();}}},[_c('button',{staticClass:"btn btn-catalogue",on:{"click":_vm.openCatalogue}},[_c('span',{staticClass:"catalogue-text"},[_vm._v("目录")])])]),_c('div',{staticClass:"zoom-hint",class:{ 'show': _vm.zoomScale !== 1 }},[_c('div',{staticClass:"zoom-info"},[_c('span',[_vm._v("缩放: "+_vm._s(Math.round(_vm.zoomScale * 100))+"%")]),_c('button',{staticClass:"btn-reset-zoom",on:{"click":_vm.resetZoom}},[_vm._v("重置")])])]),(_vm.loading)?_c('div',{staticClass:"loading-overlay"},[_vm._m(0)]):_vm._e(),(_vm.error && !_vm.loading)?_c('div',{staticClass:"error-container"},[_c('div',{staticClass:"error-content"},[_c('div',{staticClass:"error-icon"},[_vm._v("⚠️")]),_c('h3',[_vm._v("加载失败")]),_c('p',[_vm._v(_vm._s(_vm.error.message || '网络连接异常,请检查网络后重试'))]),_c('button',{staticClass:"retry-btn",on:{"click":_vm.fetchBooksData}},[_c('span',{staticClass:"retry-icon"},[_vm._v("🔄")]),_vm._v(" 重新加载 ")])])]):_vm._e(),(_vm.booksData && !_vm.loading && !_vm.error)?_c('div',{staticClass:"success-toast",class:{ 'show': _vm.showSuccessToast }},[_vm._v(" 书籍加载完成 ")]):_vm._e(),_c('book-catalogue-drawer',{attrs:{"book-id":_vm.bookId,"catalogue":_vm.catalogue,"loading":_vm.catalogueLoading},on:{"catalogue-click":_vm.onCatalogueClick,"page-jump":_vm.onPageJump,"Focus":_vm.onFocus,"fetch-catalogue":_vm.onFetchCatalogue},model:{value:(_vm.showCatalogueDrawer),callback:function ($$v) {_vm.showCatalogueDrawer=$$v},expression:"showCatalogueDrawer"}})],1)
93
+ }
94
+ var staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:"loading-container"},[_c('div',{staticClass:"loading-spinner"},[_c('div',{staticClass:"spinner-ring"}),_c('div',{staticClass:"spinner-ring"}),_c('div',{staticClass:"spinner-ring"})]),_c('div',{staticClass:"loading-text"},[_c('h3',[_vm._v("正在加载书籍")]),_c('p',[_vm._v("请稍候,正在获取精彩内容...")]),_c('div',{staticClass:"loading-progress"},[_c('div',{staticClass:"progress-bar"})])])])
95
+ }]
96
+
97
+
98
+ ;// ./src/components/BookReader.vue?vue&type=template&id=eaca7004&scoped=true
99
+
100
+ ;// ./node_modules/rematrix/dist/rematrix.es.js
101
+ /*! @license Rematrix v0.7.2
102
+
103
+ Copyright 2021 Julian Lloyd.
104
+
105
+ Permission is hereby granted, free of charge, to any person obtaining a copy
106
+ of this software and associated documentation files (the "Software"), to deal
107
+ in the Software without restriction, including without limitation the rights
108
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
109
+ copies of the Software, and to permit persons to whom the Software is
110
+ furnished to do so, subject to the following conditions:
111
+
112
+ The above copyright notice and this permission notice shall be included in
113
+ all copies or substantial portions of the Software.
114
+
115
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
116
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
117
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
118
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
119
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
120
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
121
+ THE SOFTWARE.
122
+ */
123
+ function format(source) {
124
+ if (source && source.constructor === Array) {
125
+ var values = source
126
+ .filter(function (value) { return typeof value === 'number'; })
127
+ .filter(function (value) { return !isNaN(value); });
128
+
129
+ if (source.length === 6 && values.length === 6) {
130
+ var matrix = identity();
131
+ matrix[0] = values[0];
132
+ matrix[1] = values[1];
133
+ matrix[4] = values[2];
134
+ matrix[5] = values[3];
135
+ matrix[12] = values[4];
136
+ matrix[13] = values[5];
137
+ return matrix
138
+ } else if (source.length === 16 && values.length === 16) {
139
+ return source
140
+ }
141
+ }
142
+ throw new TypeError('Expected a `number[]` with length 6 or 16.')
143
+ }
144
+
145
+ function fromString(source) {
146
+ if (typeof source === 'string') {
147
+ var match = source.match(/matrix(3d)?\(([^)]+)\)/);
148
+ if (match) {
149
+ var raw = match[2].split(',').map(parseFloat);
150
+ return format(raw)
151
+ }
152
+ if (source === 'none' || source === '') {
153
+ return identity()
154
+ }
155
+ }
156
+ throw new TypeError('Expected a string containing `matrix()` or `matrix3d()')
157
+ }
158
+
159
+ function identity() {
160
+ var matrix = [];
161
+ for (var i = 0; i < 16; i++) {
162
+ i % 5 == 0 ? matrix.push(1) : matrix.push(0);
163
+ }
164
+ return matrix
165
+ }
166
+
167
+ function inverse(source) {
168
+ var m = format(source);
169
+
170
+ var s0 = m[0] * m[5] - m[4] * m[1];
171
+ var s1 = m[0] * m[6] - m[4] * m[2];
172
+ var s2 = m[0] * m[7] - m[4] * m[3];
173
+ var s3 = m[1] * m[6] - m[5] * m[2];
174
+ var s4 = m[1] * m[7] - m[5] * m[3];
175
+ var s5 = m[2] * m[7] - m[6] * m[3];
176
+
177
+ var c5 = m[10] * m[15] - m[14] * m[11];
178
+ var c4 = m[9] * m[15] - m[13] * m[11];
179
+ var c3 = m[9] * m[14] - m[13] * m[10];
180
+ var c2 = m[8] * m[15] - m[12] * m[11];
181
+ var c1 = m[8] * m[14] - m[12] * m[10];
182
+ var c0 = m[8] * m[13] - m[12] * m[9];
183
+
184
+ var determinant = 1 / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0);
185
+
186
+ if (isNaN(determinant) || determinant === Infinity) {
187
+ throw new Error('Inverse determinant attempted to divide by zero.')
188
+ }
189
+
190
+ return [
191
+ (m[5] * c5 - m[6] * c4 + m[7] * c3) * determinant,
192
+ (-m[1] * c5 + m[2] * c4 - m[3] * c3) * determinant,
193
+ (m[13] * s5 - m[14] * s4 + m[15] * s3) * determinant,
194
+ (-m[9] * s5 + m[10] * s4 - m[11] * s3) * determinant,
195
+
196
+ (-m[4] * c5 + m[6] * c2 - m[7] * c1) * determinant,
197
+ (m[0] * c5 - m[2] * c2 + m[3] * c1) * determinant,
198
+ (-m[12] * s5 + m[14] * s2 - m[15] * s1) * determinant,
199
+ (m[8] * s5 - m[10] * s2 + m[11] * s1) * determinant,
200
+
201
+ (m[4] * c4 - m[5] * c2 + m[7] * c0) * determinant,
202
+ (-m[0] * c4 + m[1] * c2 - m[3] * c0) * determinant,
203
+ (m[12] * s4 - m[13] * s2 + m[15] * s0) * determinant,
204
+ (-m[8] * s4 + m[9] * s2 - m[11] * s0) * determinant,
205
+
206
+ (-m[4] * c3 + m[5] * c1 - m[6] * c0) * determinant,
207
+ (m[0] * c3 - m[1] * c1 + m[2] * c0) * determinant,
208
+ (-m[12] * s3 + m[13] * s1 - m[14] * s0) * determinant,
209
+ (m[8] * s3 - m[9] * s1 + m[10] * s0) * determinant ]
210
+ }
211
+
212
+ function multiply(matrixA, matrixB) {
213
+ var fma = format(matrixA);
214
+ var fmb = format(matrixB);
215
+ var product = [];
216
+
217
+ for (var i = 0; i < 4; i++) {
218
+ var row = [fma[i], fma[i + 4], fma[i + 8], fma[i + 12]];
219
+ for (var j = 0; j < 4; j++) {
220
+ var k = j * 4;
221
+ var col = [fmb[k], fmb[k + 1], fmb[k + 2], fmb[k + 3]];
222
+ var result = row[0] * col[0] + row[1] * col[1] + row[2] * col[2] + row[3] * col[3];
223
+
224
+ product[i + k] = result;
225
+ }
226
+ }
227
+
228
+ return product
229
+ }
230
+
231
+ function perspective(distance) {
232
+ var matrix = identity();
233
+ matrix[11] = -1 / distance;
234
+ return matrix
235
+ }
236
+
237
+ function rotate(angle) {
238
+ return rotateZ(angle)
239
+ }
240
+
241
+ function rotateX(angle) {
242
+ var theta = (Math.PI / 180) * angle;
243
+ var matrix = identity();
244
+
245
+ matrix[5] = matrix[10] = Math.cos(theta);
246
+ matrix[6] = matrix[9] = Math.sin(theta);
247
+ matrix[9] *= -1;
248
+
249
+ return matrix
250
+ }
251
+
252
+ function rotateY(angle) {
253
+ var theta = (Math.PI / 180) * angle;
254
+ var matrix = identity();
255
+
256
+ matrix[0] = matrix[10] = Math.cos(theta);
257
+ matrix[2] = matrix[8] = Math.sin(theta);
258
+ matrix[2] *= -1;
259
+
260
+ return matrix
261
+ }
262
+
263
+ function rotateZ(angle) {
264
+ var theta = (Math.PI / 180) * angle;
265
+ var matrix = identity();
266
+
267
+ matrix[0] = matrix[5] = Math.cos(theta);
268
+ matrix[1] = matrix[4] = Math.sin(theta);
269
+ matrix[4] *= -1;
270
+
271
+ return matrix
272
+ }
273
+
274
+ function scale(scalar, scalarY) {
275
+ var matrix = identity();
276
+
277
+ matrix[0] = scalar;
278
+ matrix[5] = typeof scalarY === 'number' ? scalarY : scalar;
279
+
280
+ return matrix
281
+ }
282
+
283
+ function scaleX(scalar) {
284
+ var matrix = identity();
285
+ matrix[0] = scalar;
286
+ return matrix
287
+ }
288
+
289
+ function scaleY(scalar) {
290
+ var matrix = identity();
291
+ matrix[5] = scalar;
292
+ return matrix
293
+ }
294
+
295
+ function scaleZ(scalar) {
296
+ var matrix = identity();
297
+ matrix[10] = scalar;
298
+ return matrix
299
+ }
300
+
301
+ function skew(angleX, angleY) {
302
+ var thetaX = (Math.PI / 180) * angleX;
303
+ var matrix = identity();
304
+
305
+ matrix[4] = Math.tan(thetaX);
306
+
307
+ if (angleY) {
308
+ var thetaY = (Math.PI / 180) * angleY;
309
+ matrix[1] = Math.tan(thetaY);
310
+ }
311
+
312
+ return matrix
313
+ }
314
+
315
+ function skewX(angle) {
316
+ var theta = (Math.PI / 180) * angle;
317
+ var matrix = identity();
318
+
319
+ matrix[4] = Math.tan(theta);
320
+
321
+ return matrix
322
+ }
323
+
324
+ function skewY(angle) {
325
+ var theta = (Math.PI / 180) * angle;
326
+ var matrix = identity();
327
+
328
+ matrix[1] = Math.tan(theta);
329
+
330
+ return matrix
331
+ }
332
+
333
+ function rematrix_es_toString(source) {
334
+ return ("matrix3d(" + (format(source).join(', ')) + ")")
335
+ }
336
+
337
+ function translate(distanceX, distanceY) {
338
+ var matrix = identity();
339
+ matrix[12] = distanceX;
340
+
341
+ if (distanceY) {
342
+ matrix[13] = distanceY;
343
+ }
344
+
345
+ return matrix
346
+ }
347
+
348
+ function translate3d(distanceX, distanceY, distanceZ) {
349
+ var matrix = identity();
350
+ if (distanceX !== undefined && distanceY !== undefined && distanceZ !== undefined) {
351
+ matrix[12] = distanceX;
352
+ matrix[13] = distanceY;
353
+ matrix[14] = distanceZ;
354
+ }
355
+ return matrix
356
+ }
357
+
358
+ function translateX(distance) {
359
+ var matrix = identity();
360
+ matrix[12] = distance;
361
+ return matrix
362
+ }
363
+
364
+ function translateY(distance) {
365
+ var matrix = identity();
366
+ matrix[13] = distance;
367
+ return matrix
368
+ }
369
+
370
+ function translateZ(distance) {
371
+ var matrix = identity();
372
+ matrix[14] = distance;
373
+ return matrix
374
+ }
375
+
376
+
377
+
378
+ ;// ./node_modules/flipbook-vue/dist/vue2/flipbook.mjs
379
+ /*!
380
+ * @license
381
+ * flipbook-vue v1.0.0-beta.4
382
+ * Copyright © 2023 Takeshi Sone.
383
+ * Released under the MIT License.
384
+ */
385
+
386
+
387
+
388
+ var Matrix = /*@__PURE__*/(function () {
389
+ function Matrix(arg) {
390
+ if (arg) {
391
+ if (arg.m) {
392
+ this.m = [].concat( arg.m );
393
+ } else {
394
+ this.m = [].concat( arg );
395
+ }
396
+ } else {
397
+ this.m = identity();
398
+ }
399
+ }
400
+
401
+ Matrix.prototype.clone = function clone () {
402
+ return new Matrix(this);
403
+ };
404
+
405
+ Matrix.prototype.multiply = function multiply$1 (m) {
406
+ return this.m = multiply(this.m, m);
407
+ };
408
+
409
+ Matrix.prototype.perspective = function perspective$1 (d) {
410
+ return this.multiply(perspective(d));
411
+ };
412
+
413
+ Matrix.prototype.transformX = function transformX (x) {
414
+ return (x * this.m[0] + this.m[12]) / (x * this.m[3] + this.m[15]);
415
+ };
416
+
417
+ Matrix.prototype.translate = function translate$1 (x, y) {
418
+ return this.multiply(translate(x, y));
419
+ };
420
+
421
+ Matrix.prototype.translate3d = function translate3d$1 (x, y, z) {
422
+ return this.multiply(translate3d(x, y, z));
423
+ };
424
+
425
+ Matrix.prototype.rotateY = function rotateY$1 (deg) {
426
+ return this.multiply(rotateY(deg));
427
+ };
428
+
429
+ Matrix.prototype.toString = function toString$1 () {
430
+ return rematrix_es_toString(this.m);
431
+ };
432
+
433
+ return Matrix;
434
+ }());
435
+
436
+ var spinner = "data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22500%22%20height%3D%22500%22%20viewBox%3D%220%200%20500%20500%22%20fill%3D%22transparent%22%20style%3D%22background-color%3A%20%23fff%22%3E%20%20%3Ccircle%20%20%20%20cx%3D%22250%22%20%20%20%20cy%3D%22250%22%20%20%20%20r%3D%2248%22%20%20%20%20stroke%3D%22%23333%22%20%20%20%20stroke-width%3D%222%22%20%20%20%20stroke-dasharray%3D%22271%2030%22%20%20%3E%20%20%20%20%3CanimateTransform%20%20%20%20%20%20attributeName%3D%22transform%22%20%20%20%20%20%20attributeType%3D%22XML%22%20%20%20%20%20%20type%3D%22rotate%22%20%20%20%20%20%20from%3D%220%20250%20250%22%20%20%20%20%20%20to%3D%22360%20250%20250%22%20%20%20%20%20%20dur%3D%221s%22%20%20%20%20%20%20repeatCount%3D%22indefinite%22%20%20%20%20%2F%3E%20%20%3C%2Fcircle%3E%3C%2Fsvg%3E";
437
+
438
+ var easeIn, easeInOut, easeOut;
439
+
440
+ easeIn = function(x) {
441
+ return Math.pow(x, 2);
442
+ };
443
+
444
+ easeOut = function(x) {
445
+ return 1 - easeIn(1 - x);
446
+ };
447
+
448
+ easeInOut = function(x) {
449
+ if (x < 0.5) {
450
+ return easeIn(x * 2) / 2;
451
+ } else {
452
+ return 0.5 + easeOut((x - 0.5) * 2) / 2;
453
+ }
454
+ };
455
+
456
+ var script = {
457
+ props: {
458
+ pages: {
459
+ type: Array,
460
+ required: true
461
+ },
462
+ pagesHiRes: {
463
+ type: Array,
464
+ default: function() {
465
+ return [];
466
+ }
467
+ },
468
+ flipDuration: {
469
+ type: Number,
470
+ default: 1000
471
+ },
472
+ zoomDuration: {
473
+ type: Number,
474
+ default: 500
475
+ },
476
+ zooms: {
477
+ type: Array,
478
+ default: function() {
479
+ return [1, 2, 4];
480
+ }
481
+ },
482
+ perspective: {
483
+ type: Number,
484
+ default: 2400
485
+ },
486
+ nPolygons: {
487
+ type: Number,
488
+ default: 10
489
+ },
490
+ ambient: {
491
+ type: Number,
492
+ default: 0.4
493
+ },
494
+ gloss: {
495
+ type: Number,
496
+ default: 0.6
497
+ },
498
+ swipeMin: {
499
+ type: Number,
500
+ default: 3
501
+ },
502
+ singlePage: {
503
+ type: Boolean,
504
+ default: false
505
+ },
506
+ forwardDirection: {
507
+ validator: function(val) {
508
+ return val === 'right' || val === 'left';
509
+ },
510
+ default: 'right'
511
+ },
512
+ centering: {
513
+ type: Boolean,
514
+ default: true
515
+ },
516
+ startPage: {
517
+ type: Number,
518
+ default: null
519
+ },
520
+ loadingImage: {
521
+ type: String,
522
+ default: spinner
523
+ },
524
+ clickToZoom: {
525
+ type: Boolean,
526
+ default: true
527
+ },
528
+ dragToFlip: {
529
+ type: Boolean,
530
+ default: true
531
+ },
532
+ wheel: {
533
+ type: String,
534
+ default: 'scroll'
535
+ }
536
+ },
537
+ data: function() {
538
+ return {
539
+ viewWidth: 0,
540
+ viewHeight: 0,
541
+ imageWidth: null,
542
+ imageHeight: null,
543
+ displayedPages: 1,
544
+ nImageLoad: 0,
545
+ nImageLoadTrigger: 0,
546
+ imageLoadCallback: null,
547
+ currentPage: 0,
548
+ firstPage: 0,
549
+ secondPage: 1,
550
+ zoomIndex: 0,
551
+ zoom: 1,
552
+ zooming: false,
553
+ touchStartX: null,
554
+ touchStartY: null,
555
+ maxMove: 0,
556
+ activeCursor: null,
557
+ hasTouchEvents: false,
558
+ hasPointerEvents: false,
559
+ minX: 2e308,
560
+ maxX: -2e308,
561
+ preloadedImages: {},
562
+ flip: {
563
+ progress: 0,
564
+ direction: null,
565
+ frontImage: null,
566
+ backImage: null,
567
+ auto: false,
568
+ opacity: 1
569
+ },
570
+ currentCenterOffset: null,
571
+ animatingCenter: false,
572
+ startScrollLeft: 0,
573
+ startScrollTop: 0,
574
+ scrollLeft: 0,
575
+ scrollTop: 0,
576
+ loadedImages: {}
577
+ };
578
+ },
579
+ computed: {
580
+ IE: function() {
581
+ return typeof navigator !== 'undefined' && /Trident/.test(navigator.userAgent);
582
+ },
583
+ canFlipLeft: function() {
584
+ if (this.forwardDirection === 'left') {
585
+ return this.canGoForward;
586
+ } else {
587
+ return this.canGoBack;
588
+ }
589
+ },
590
+ canFlipRight: function() {
591
+ if (this.forwardDirection === 'right') {
592
+ return this.canGoForward;
593
+ } else {
594
+ return this.canGoBack;
595
+ }
596
+ },
597
+ canZoomIn: function() {
598
+ return !this.zooming && this.zoomIndex < this.zooms_.length - 1;
599
+ },
600
+ canZoomOut: function() {
601
+ return !this.zooming && this.zoomIndex > 0;
602
+ },
603
+ numPages: function() {
604
+ if (this.pages[0] === null) {
605
+ return this.pages.length - 1;
606
+ } else {
607
+ return this.pages.length;
608
+ }
609
+ },
610
+ page: function() {
611
+ if (this.pages[0] !== null) {
612
+ return this.currentPage + 1;
613
+ } else {
614
+ return Math.max(1, this.currentPage);
615
+ }
616
+ },
617
+ zooms_: function() {
618
+ return this.zooms || [1];
619
+ },
620
+ canGoForward: function() {
621
+ return !this.flip.direction && this.currentPage < this.pages.length - this.displayedPages;
622
+ },
623
+ canGoBack: function() {
624
+ return !this.flip.direction && this.currentPage >= this.displayedPages && !(this.displayedPages === 1 && !this.pageUrl(this.firstPage - 1));
625
+ },
626
+ leftPage: function() {
627
+ if (this.forwardDirection === 'right' || this.displayedPages === 1) {
628
+ return this.firstPage;
629
+ } else {
630
+ return this.secondPage;
631
+ }
632
+ },
633
+ rightPage: function() {
634
+ if (this.forwardDirection === 'left') {
635
+ return this.firstPage;
636
+ } else {
637
+ return this.secondPage;
638
+ }
639
+ },
640
+ showLeftPage: function() {
641
+ return this.pageUrl(this.leftPage);
642
+ },
643
+ showRightPage: function() {
644
+ return this.pageUrl(this.rightPage) && this.displayedPages === 2;
645
+ },
646
+ cursor: function() {
647
+ if (this.activeCursor) {
648
+ return this.activeCursor;
649
+ } else if (this.IE) {
650
+ return 'auto';
651
+ } else if (this.clickToZoom && this.canZoomIn) {
652
+ return 'zoom-in';
653
+ } else if (this.clickToZoom && this.canZoomOut) {
654
+ return 'zoom-out';
655
+ } else if (this.dragToFlip) {
656
+ return 'grab';
657
+ } else {
658
+ return 'auto';
659
+ }
660
+ },
661
+ pageScale: function() {
662
+ var scale, vw, xScale, yScale;
663
+ vw = this.viewWidth / this.displayedPages;
664
+ xScale = vw / this.imageWidth;
665
+ yScale = this.viewHeight / this.imageHeight;
666
+ scale = xScale < yScale ? xScale : yScale;
667
+ if (scale < 1) {
668
+ return scale;
669
+ } else {
670
+ return 1;
671
+ }
672
+ },
673
+ pageWidth: function() {
674
+ return Math.round(this.imageWidth * this.pageScale);
675
+ },
676
+ pageHeight: function() {
677
+ return Math.round(this.imageHeight * this.pageScale);
678
+ },
679
+ xMargin: function() {
680
+ return (this.viewWidth - this.pageWidth * this.displayedPages) / 2;
681
+ },
682
+ yMargin: function() {
683
+ return (this.viewHeight - this.pageHeight) / 2;
684
+ },
685
+ polygonWidth: function() {
686
+ var w;
687
+ w = this.pageWidth / this.nPolygons;
688
+ w = Math.ceil(w + 1 / this.zoom);
689
+ return w + 'px';
690
+ },
691
+ polygonHeight: function() {
692
+ return this.pageHeight + 'px';
693
+ },
694
+ polygonBgSize: function() {
695
+ return ((this.pageWidth) + "px " + (this.pageHeight) + "px");
696
+ },
697
+ polygonArray: function() {
698
+ return this.makePolygonArray('front').concat(this.makePolygonArray('back'));
699
+ },
700
+ boundingLeft: function() {
701
+ var x;
702
+ if (this.displayedPages === 1) {
703
+ return this.xMargin;
704
+ } else {
705
+ x = this.pageUrl(this.leftPage) ? this.xMargin : this.viewWidth / 2;
706
+ if (x < this.minX) {
707
+ return x;
708
+ } else {
709
+ return this.minX;
710
+ }
711
+ }
712
+ },
713
+ boundingRight: function() {
714
+ var x;
715
+ if (this.displayedPages === 1) {
716
+ return this.viewWidth - this.xMargin;
717
+ } else {
718
+ x = this.pageUrl(this.rightPage) ? this.viewWidth - this.xMargin : this.viewWidth / 2;
719
+ if (x > this.maxX) {
720
+ return x;
721
+ } else {
722
+ return this.maxX;
723
+ }
724
+ }
725
+ },
726
+ centerOffset: function() {
727
+ var retval;
728
+ retval = this.centering ? Math.round(this.viewWidth / 2 - (this.boundingLeft + this.boundingRight) / 2) : 0;
729
+ if (this.currentCenterOffset === null && this.imageWidth !== null) {
730
+ this.currentCenterOffset = retval;
731
+ }
732
+ return retval;
733
+ },
734
+ centerOffsetSmoothed: function() {
735
+ return Math.round(this.currentCenterOffset);
736
+ },
737
+ dragToScroll: function() {
738
+ return !this.hasTouchEvents;
739
+ },
740
+ scrollLeftMin: function() {
741
+ var w;
742
+ w = (this.boundingRight - this.boundingLeft) * this.zoom;
743
+ if (w < this.viewWidth) {
744
+ return (this.boundingLeft + this.centerOffsetSmoothed) * this.zoom - (this.viewWidth - w) / 2;
745
+ } else {
746
+ return (this.boundingLeft + this.centerOffsetSmoothed) * this.zoom;
747
+ }
748
+ },
749
+ scrollLeftMax: function() {
750
+ var w;
751
+ w = (this.boundingRight - this.boundingLeft) * this.zoom;
752
+ if (w < this.viewWidth) {
753
+ return (this.boundingLeft + this.centerOffsetSmoothed) * this.zoom - (this.viewWidth - w) / 2;
754
+ } else {
755
+ return (this.boundingRight + this.centerOffsetSmoothed) * this.zoom - this.viewWidth;
756
+ }
757
+ },
758
+ scrollTopMin: function() {
759
+ var h;
760
+ h = this.pageHeight * this.zoom;
761
+ if (h < this.viewHeight) {
762
+ return this.yMargin * this.zoom - (this.viewHeight - h) / 2;
763
+ } else {
764
+ return this.yMargin * this.zoom;
765
+ }
766
+ },
767
+ scrollTopMax: function() {
768
+ var h;
769
+ h = this.pageHeight * this.zoom;
770
+ if (h < this.viewHeight) {
771
+ return this.yMargin * this.zoom - (this.viewHeight - h) / 2;
772
+ } else {
773
+ return (this.yMargin + this.pageHeight) * this.zoom - this.viewHeight;
774
+ }
775
+ },
776
+ scrollLeftLimited: function() {
777
+ return Math.min(this.scrollLeftMax, Math.max(this.scrollLeftMin, this.scrollLeft));
778
+ },
779
+ scrollTopLimited: function() {
780
+ return Math.min(this.scrollTopMax, Math.max(this.scrollTopMin, this.scrollTop));
781
+ }
782
+ },
783
+ mounted: function() {
784
+ window.addEventListener('resize', this.onResize, {
785
+ passive: true
786
+ });
787
+ this.onResize();
788
+ this.zoom = this.zooms_[0];
789
+ return this.goToPage(this.startPage);
790
+ },
791
+ beforeDestroy: function() {
792
+ return window.removeEventListener('resize', this.onResize, {
793
+ passive: true
794
+ });
795
+ },
796
+ methods: {
797
+ onResize: function() {
798
+ var viewport;
799
+ viewport = this.$refs.viewport;
800
+ if (!viewport) {
801
+ return;
802
+ }
803
+ this.viewWidth = viewport.clientWidth;
804
+ this.viewHeight = viewport.clientHeight;
805
+ this.displayedPages = this.viewWidth > this.viewHeight && !this.singlePage ? 2 : 1;
806
+ if (this.displayedPages === 2) {
807
+ this.currentPage &= ~1;
808
+ }
809
+ this.fixFirstPage();
810
+ this.minX = 2e308;
811
+ return this.maxX = -2e308;
812
+ },
813
+ fixFirstPage: function() {
814
+ if (this.displayedPages === 1 && this.currentPage === 0 && this.pages.length && !this.pageUrl(0)) {
815
+ return this.currentPage++;
816
+ }
817
+ },
818
+ pageUrl: function(page, hiRes) {
819
+ if ( hiRes === void 0 ) hiRes = false;
820
+
821
+ var url;
822
+ if (hiRes && this.zoom > 1 && !this.zooming) {
823
+ url = this.pagesHiRes[page];
824
+ if (url) {
825
+ return url;
826
+ }
827
+ }
828
+ return this.pages[page] || null;
829
+ },
830
+ pageUrlLoading: function(page, hiRes) {
831
+ if ( hiRes === void 0 ) hiRes = false;
832
+
833
+ var url;
834
+ url = this.pageUrl(page, hiRes);
835
+ if (hiRes && this.zoom > 1 && !this.zooming) {
836
+ // High-res image doesn't use 'loading'
837
+ return url;
838
+ }
839
+ return url && this.loadImage(url);
840
+ },
841
+ flipLeft: function() {
842
+ if (!this.canFlipLeft) {
843
+ return;
844
+ }
845
+ return this.flipStart('left', true);
846
+ },
847
+ flipRight: function() {
848
+ if (!this.canFlipRight) {
849
+ return;
850
+ }
851
+ return this.flipStart('right', true);
852
+ },
853
+ makePolygonArray: function(face) {
854
+ var bgPos, dRadian, dRotate, direction, i, image, j, lighting, m, originRight, pageMatrix, pageRotation, pageX, polygonWidth, progress, rad, radian, radius, ref, results, rotate, theta, x, x0, x1, z;
855
+ if (!this.flip.direction) {
856
+ return [];
857
+ }
858
+ progress = this.flip.progress;
859
+ direction = this.flip.direction;
860
+ if (this.displayedPages === 1 && direction !== this.forwardDirection) {
861
+ progress = 1 - progress;
862
+ direction = this.forwardDirection;
863
+ }
864
+ this.flip.opacity = this.displayedPages === 1 && progress > .7 ? 1 - (progress - .7) / .3 : 1;
865
+ image = face === 'front' ? this.flip.frontImage : this.flip.backImage;
866
+ polygonWidth = this.pageWidth / this.nPolygons;
867
+ pageX = this.xMargin;
868
+ originRight = false;
869
+ if (this.displayedPages === 1) {
870
+ if (this.forwardDirection === 'right') {
871
+ if (face === 'back') {
872
+ originRight = true;
873
+ pageX = this.xMargin - this.pageWidth;
874
+ }
875
+ } else {
876
+ if (direction === 'left') {
877
+ if (face === 'back') {
878
+ pageX = this.pageWidth - this.xMargin;
879
+ } else {
880
+ originRight = true;
881
+ }
882
+ } else {
883
+ if (face === 'front') {
884
+ pageX = this.pageWidth - this.xMargin;
885
+ } else {
886
+ originRight = true;
887
+ }
888
+ }
889
+ }
890
+ } else {
891
+ if (direction === 'left') {
892
+ if (face === 'back') {
893
+ pageX = this.viewWidth / 2;
894
+ } else {
895
+ originRight = true;
896
+ }
897
+ } else {
898
+ if (face === 'front') {
899
+ pageX = this.viewWidth / 2;
900
+ } else {
901
+ originRight = true;
902
+ }
903
+ }
904
+ }
905
+ pageMatrix = new Matrix();
906
+ pageMatrix.translate(this.viewWidth / 2);
907
+ pageMatrix.perspective(this.perspective);
908
+ pageMatrix.translate(-this.viewWidth / 2);
909
+ pageMatrix.translate(pageX, this.yMargin);
910
+ pageRotation = 0;
911
+ if (progress > 0.5) {
912
+ pageRotation = -(progress - 0.5) * 2 * 180;
913
+ }
914
+ if (direction === 'left') {
915
+ pageRotation = -pageRotation;
916
+ }
917
+ if (face === 'back') {
918
+ pageRotation += 180;
919
+ }
920
+ if (pageRotation) {
921
+ if (originRight) {
922
+ pageMatrix.translate(this.pageWidth);
923
+ }
924
+ pageMatrix.rotateY(pageRotation);
925
+ if (originRight) {
926
+ pageMatrix.translate(-this.pageWidth);
927
+ }
928
+ }
929
+ if (progress < 0.5) {
930
+ theta = progress * 2 * Math.PI;
931
+ } else {
932
+ theta = (1 - (progress - 0.5) * 2) * Math.PI;
933
+ }
934
+ if (theta === 0) {
935
+ theta = 1e-9;
936
+ }
937
+ radius = this.pageWidth / theta;
938
+ radian = 0;
939
+ dRadian = theta / this.nPolygons;
940
+ rotate = dRadian / 2 / Math.PI * 180;
941
+ dRotate = dRadian / Math.PI * 180;
942
+ if (originRight) {
943
+ rotate = -theta / Math.PI * 180 + dRotate / 2;
944
+ }
945
+ if (face === 'back') {
946
+ rotate = -rotate;
947
+ dRotate = -dRotate;
948
+ }
949
+ this.minX = 2e308;
950
+ this.maxX = -2e308;
951
+ results = [];
952
+ for (i = j = 0, ref = this.nPolygons; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
953
+ bgPos = (i / (this.nPolygons - 1) * 100) + "% 0px";
954
+ m = pageMatrix.clone();
955
+ rad = originRight ? theta - radian : radian;
956
+ x = Math.sin(rad) * radius;
957
+ if (originRight) {
958
+ x = this.pageWidth - x;
959
+ }
960
+ z = (1 - Math.cos(rad)) * radius;
961
+ if (face === 'back') {
962
+ z = -z;
963
+ }
964
+ m.translate3d(x, 0, z);
965
+ m.rotateY(-rotate);
966
+ x0 = m.transformX(0);
967
+ x1 = m.transformX(polygonWidth);
968
+ this.maxX = Math.max(Math.max(x0, x1), this.maxX);
969
+ this.minX = Math.min(Math.min(x0, x1), this.minX);
970
+ lighting = this.computeLighting(pageRotation - rotate, dRotate);
971
+ radian += dRadian;
972
+ rotate += dRotate;
973
+ results.push([face + i, image, lighting, bgPos, m.toString(), Math.abs(Math.round(z))]);
974
+ }
975
+ return results;
976
+ },
977
+ computeLighting: function(rot, dRotate) {
978
+ var DEG, POW, blackness, diffuse, gradients, lightingPoints, specular;
979
+ gradients = [];
980
+ lightingPoints = [-0.5, -0.25, 0, 0.25, 0.5];
981
+ if (this.ambient < 1) {
982
+ blackness = 1 - this.ambient;
983
+ diffuse = lightingPoints.map(function (d) {
984
+ return (1 - Math.cos((rot - dRotate * d) / 180 * Math.PI)) * blackness;
985
+ });
986
+ gradients.push(("linear-gradient(to right,\n rgba(0, 0, 0, " + (diffuse[0]) + "),\n rgba(0, 0, 0, " + (diffuse[1]) + ") 25%,\n rgba(0, 0, 0, " + (diffuse[2]) + ") 50%,\n rgba(0, 0, 0, " + (diffuse[3]) + ") 75%,\n rgba(0, 0, 0, " + (diffuse[4]) + "))"));
987
+ }
988
+ if (this.gloss > 0 && !this.IE) {
989
+ DEG = 30;
990
+ POW = 200;
991
+ specular = lightingPoints.map(function (d) {
992
+ return Math.max(Math.pow( Math.cos((rot + DEG - dRotate * d) / 180 * Math.PI), POW ), Math.pow( Math.cos((rot - DEG - dRotate * d) / 180 * Math.PI), POW ));
993
+ });
994
+ gradients.push(("linear-gradient(to right,\n rgba(255, 255, 255, " + (specular[0] * this.gloss) + "),\n rgba(255, 255, 255, " + (specular[1] * this.gloss) + ") 25%,\n rgba(255, 255, 255, " + (specular[2] * this.gloss) + ") 50%,\n rgba(255, 255, 255, " + (specular[3] * this.gloss) + ") 75%,\n rgba(255, 255, 255, " + (specular[4] * this.gloss) + "))"));
995
+ }
996
+ return gradients.join(',');
997
+ },
998
+ flipStart: function(direction, auto) {
999
+ var this$1$1 = this;
1000
+
1001
+ if (direction !== this.forwardDirection) {
1002
+ if (this.displayedPages === 1) {
1003
+ this.flip.frontImage = this.pageUrl(this.currentPage - 1);
1004
+ this.flip.backImage = null;
1005
+ } else {
1006
+ this.flip.frontImage = this.pageUrl(this.firstPage);
1007
+ this.flip.backImage = this.pageUrl(this.currentPage - this.displayedPages + 1);
1008
+ }
1009
+ } else {
1010
+ if (this.displayedPages === 1) {
1011
+ this.flip.frontImage = this.pageUrl(this.currentPage);
1012
+ this.flip.backImage = null;
1013
+ } else {
1014
+ this.flip.frontImage = this.pageUrl(this.secondPage);
1015
+ this.flip.backImage = this.pageUrl(this.currentPage + this.displayedPages);
1016
+ }
1017
+ }
1018
+ this.flip.direction = direction;
1019
+ this.flip.progress = 0;
1020
+ return requestAnimationFrame(function () {
1021
+ return requestAnimationFrame(function () {
1022
+ if (this$1$1.flip.direction !== this$1$1.forwardDirection) {
1023
+ if (this$1$1.displayedPages === 2) {
1024
+ this$1$1.firstPage = this$1$1.currentPage - this$1$1.displayedPages;
1025
+ }
1026
+ } else {
1027
+ if (this$1$1.displayedPages === 1) {
1028
+ this$1$1.firstPage = this$1$1.currentPage + this$1$1.displayedPages;
1029
+ } else {
1030
+ this$1$1.secondPage = this$1$1.currentPage + 1 + this$1$1.displayedPages;
1031
+ }
1032
+ }
1033
+ if (auto) {
1034
+ return this$1$1.flipAuto(true);
1035
+ }
1036
+ });
1037
+ });
1038
+ },
1039
+ flipAuto: function(ease) {
1040
+ var this$1$1 = this;
1041
+
1042
+ var animate, duration, startRatio, t0;
1043
+ t0 = Date.now();
1044
+ duration = this.flipDuration * (1 - this.flip.progress);
1045
+ startRatio = this.flip.progress;
1046
+ this.flip.auto = true;
1047
+ this.$emit(("flip-" + (this.flip.direction) + "-start"), this.page);
1048
+ animate = function () {
1049
+ return requestAnimationFrame(function () {
1050
+ var ratio, t;
1051
+ t = Date.now() - t0;
1052
+ ratio = startRatio + t / duration;
1053
+ if (ratio > 1) {
1054
+ ratio = 1;
1055
+ }
1056
+ this$1$1.flip.progress = ease ? easeInOut(ratio) : ratio;
1057
+ if (ratio < 1) {
1058
+ return animate();
1059
+ } else {
1060
+ if (this$1$1.flip.direction !== this$1$1.forwardDirection) {
1061
+ this$1$1.currentPage -= this$1$1.displayedPages;
1062
+ } else {
1063
+ this$1$1.currentPage += this$1$1.displayedPages;
1064
+ }
1065
+ this$1$1.$emit(("flip-" + (this$1$1.flip.direction) + "-end"), this$1$1.page);
1066
+ if (this$1$1.displayedPages === 1 && this$1$1.flip.direction === this$1$1.forwardDirection) {
1067
+ this$1$1.flip.direction = null;
1068
+ } else {
1069
+ this$1$1.onImageLoad(1, function () {
1070
+ return this$1$1.flip.direction = null;
1071
+ });
1072
+ }
1073
+ return this$1$1.flip.auto = false;
1074
+ }
1075
+ });
1076
+ };
1077
+ return animate();
1078
+ },
1079
+ flipRevert: function() {
1080
+ var this$1$1 = this;
1081
+
1082
+ var animate, duration, startRatio, t0;
1083
+ t0 = Date.now();
1084
+ duration = this.flipDuration * this.flip.progress;
1085
+ startRatio = this.flip.progress;
1086
+ this.flip.auto = true;
1087
+ animate = function () {
1088
+ return requestAnimationFrame(function () {
1089
+ var ratio, t;
1090
+ t = Date.now() - t0;
1091
+ ratio = startRatio - startRatio * t / duration;
1092
+ if (ratio < 0) {
1093
+ ratio = 0;
1094
+ }
1095
+ this$1$1.flip.progress = ratio;
1096
+ if (ratio > 0) {
1097
+ return animate();
1098
+ } else {
1099
+ this$1$1.firstPage = this$1$1.currentPage;
1100
+ this$1$1.secondPage = this$1$1.currentPage + 1;
1101
+ if (this$1$1.displayedPages === 1 && this$1$1.flip.direction !== this$1$1.forwardDirection) {
1102
+ this$1$1.flip.direction = null;
1103
+ } else {
1104
+ this$1$1.onImageLoad(1, function () {
1105
+ return this$1$1.flip.direction = null;
1106
+ });
1107
+ }
1108
+ return this$1$1.flip.auto = false;
1109
+ }
1110
+ });
1111
+ };
1112
+ return animate();
1113
+ },
1114
+ onImageLoad: function(trigger, cb) {
1115
+ this.nImageLoad = 0;
1116
+ this.nImageLoadTrigger = trigger;
1117
+ return this.imageLoadCallback = cb;
1118
+ },
1119
+ didLoadImage: function(ev) {
1120
+ if (this.imageWidth === null) {
1121
+ this.imageWidth = (ev.target || ev.path[0]).naturalWidth;
1122
+ this.imageHeight = (ev.target || ev.path[0]).naturalHeight;
1123
+ this.preloadImages();
1124
+ }
1125
+ if (!this.imageLoadCallback) {
1126
+ return;
1127
+ }
1128
+ if (++this.nImageLoad >= this.nImageLoadTrigger) {
1129
+ this.imageLoadCallback();
1130
+ return this.imageLoadCallback = null;
1131
+ }
1132
+ },
1133
+ zoomIn: function(zoomAt) {
1134
+ if ( zoomAt === void 0 ) zoomAt = null;
1135
+
1136
+ if (!this.canZoomIn) {
1137
+ return;
1138
+ }
1139
+ this.zoomIndex += 1;
1140
+ return this.zoomTo(this.zooms_[this.zoomIndex], zoomAt);
1141
+ },
1142
+ zoomOut: function(zoomAt) {
1143
+ if ( zoomAt === void 0 ) zoomAt = null;
1144
+
1145
+ if (!this.canZoomOut) {
1146
+ return;
1147
+ }
1148
+ this.zoomIndex -= 1;
1149
+ return this.zoomTo(this.zooms_[this.zoomIndex], zoomAt);
1150
+ },
1151
+ zoomTo: function(zoom, zoomAt) {
1152
+ var this$1$1 = this;
1153
+ if ( zoomAt === void 0 ) zoomAt = null;
1154
+
1155
+ var animate, containerFixedX, containerFixedY, end, endX, endY, fixedX, fixedY, rect, start, startX, startY, t0, viewport;
1156
+ viewport = this.$refs.viewport;
1157
+ if (zoomAt) {
1158
+ rect = viewport.getBoundingClientRect();
1159
+ fixedX = zoomAt.pageX - rect.left;
1160
+ fixedY = zoomAt.pageY - rect.top;
1161
+ } else {
1162
+ fixedX = viewport.clientWidth / 2;
1163
+ fixedY = viewport.clientHeight / 2;
1164
+ }
1165
+ start = this.zoom;
1166
+ end = zoom;
1167
+ startX = viewport.scrollLeft;
1168
+ startY = viewport.scrollTop;
1169
+ containerFixedX = fixedX + startX;
1170
+ containerFixedY = fixedY + startY;
1171
+ endX = containerFixedX / start * end - fixedX;
1172
+ endY = containerFixedY / start * end - fixedY;
1173
+ t0 = Date.now();
1174
+ this.zooming = true;
1175
+ this.$emit('zoom-start', zoom);
1176
+ animate = function () {
1177
+ return requestAnimationFrame(function () {
1178
+ var ratio, t;
1179
+ t = Date.now() - t0;
1180
+ ratio = t / this$1$1.zoomDuration;
1181
+ if (ratio > 1 || this$1$1.IE) {
1182
+ ratio = 1;
1183
+ }
1184
+ ratio = easeInOut(ratio);
1185
+ this$1$1.zoom = start + (end - start) * ratio;
1186
+ this$1$1.scrollLeft = startX + (endX - startX) * ratio;
1187
+ this$1$1.scrollTop = startY + (endY - startY) * ratio;
1188
+ if (t < this$1$1.zoomDuration) {
1189
+ return animate();
1190
+ } else {
1191
+ this$1$1.$emit('zoom-end', zoom);
1192
+ this$1$1.zooming = false;
1193
+ this$1$1.zoom = zoom;
1194
+ this$1$1.scrollLeft = endX;
1195
+ return this$1$1.scrollTop = endY;
1196
+ }
1197
+ });
1198
+ };
1199
+ animate();
1200
+ if (end > 1) {
1201
+ return this.preloadImages(true);
1202
+ }
1203
+ },
1204
+ zoomAt: function(zoomAt) {
1205
+ this.zoomIndex = (this.zoomIndex + 1) % this.zooms_.length;
1206
+ return this.zoomTo(this.zooms_[this.zoomIndex], zoomAt);
1207
+ },
1208
+ swipeStart: function(touch) {
1209
+ this.touchStartX = touch.pageX;
1210
+ this.touchStartY = touch.pageY;
1211
+ this.maxMove = 0;
1212
+ if (this.zoom <= 1) {
1213
+ if (this.dragToFlip) {
1214
+ return this.activeCursor = 'grab';
1215
+ }
1216
+ } else {
1217
+ this.startScrollLeft = this.$refs.viewport.scrollLeft;
1218
+ this.startScrollTop = this.$refs.viewport.scrollTop;
1219
+ return this.activeCursor = 'all-scroll';
1220
+ }
1221
+ },
1222
+ swipeMove: function(touch) {
1223
+ var x, y;
1224
+ if (this.touchStartX == null) {
1225
+ return;
1226
+ }
1227
+ x = touch.pageX - this.touchStartX;
1228
+ y = touch.pageY - this.touchStartY;
1229
+ this.maxMove = Math.max(this.maxMove, Math.abs(x));
1230
+ this.maxMove = Math.max(this.maxMove, Math.abs(y));
1231
+ if (this.zoom > 1) {
1232
+ if (this.dragToScroll) {
1233
+ this.dragScroll(x, y);
1234
+ }
1235
+ return;
1236
+ }
1237
+ if (!this.dragToFlip) {
1238
+ return;
1239
+ }
1240
+ if (Math.abs(y) > Math.abs(x)) {
1241
+ return;
1242
+ }
1243
+ this.activeCursor = 'grabbing';
1244
+ if (x > 0) {
1245
+ if (this.flip.direction === null && this.canFlipLeft && x >= this.swipeMin) {
1246
+ this.flipStart('left', false);
1247
+ }
1248
+ if (this.flip.direction === 'left') {
1249
+ this.flip.progress = x / this.pageWidth;
1250
+ if (this.flip.progress > 1) {
1251
+ this.flip.progress = 1;
1252
+ }
1253
+ }
1254
+ } else {
1255
+ if (this.flip.direction === null && this.canFlipRight && x <= -this.swipeMin) {
1256
+ this.flipStart('right', false);
1257
+ }
1258
+ if (this.flip.direction === 'right') {
1259
+ this.flip.progress = -x / this.pageWidth;
1260
+ if (this.flip.progress > 1) {
1261
+ this.flip.progress = 1;
1262
+ }
1263
+ }
1264
+ }
1265
+ return true;
1266
+ },
1267
+ swipeEnd: function(touch) {
1268
+ if (this.touchStartX == null) {
1269
+ return;
1270
+ }
1271
+ if (this.clickToZoom && this.maxMove < this.swipeMin) {
1272
+ this.zoomAt(touch);
1273
+ }
1274
+ if (this.flip.direction !== null && !this.flip.auto) {
1275
+ if (this.flip.progress > 1 / 4) {
1276
+ this.flipAuto(false);
1277
+ } else {
1278
+ this.flipRevert();
1279
+ }
1280
+ }
1281
+ this.touchStartX = null;
1282
+ return this.activeCursor = null;
1283
+ },
1284
+ onTouchStart: function(ev) {
1285
+ this.hasTouchEvents = true;
1286
+ return this.swipeStart(ev.changedTouches[0]);
1287
+ },
1288
+ onTouchMove: function(ev) {
1289
+ if (this.swipeMove(ev.changedTouches[0])) {
1290
+ if (ev.cancelable) {
1291
+ return ev.preventDefault();
1292
+ }
1293
+ }
1294
+ },
1295
+ onTouchEnd: function(ev) {
1296
+ return this.swipeEnd(ev.changedTouches[0]);
1297
+ },
1298
+ onPointerDown: function(ev) {
1299
+ this.hasPointerEvents = true;
1300
+ if (this.hasTouchEvents) {
1301
+ return;
1302
+ }
1303
+ if (ev.which && ev.which !== 1) { // Ignore right-click
1304
+ return;
1305
+ }
1306
+ this.swipeStart(ev);
1307
+ try {
1308
+ return ev.target.setPointerCapture(ev.pointerId);
1309
+ } catch (error) {
1310
+
1311
+ }
1312
+ },
1313
+ onPointerMove: function(ev) {
1314
+ if (!this.hasTouchEvents) {
1315
+ return this.swipeMove(ev);
1316
+ }
1317
+ },
1318
+ onPointerUp: function(ev) {
1319
+ if (this.hasTouchEvents) {
1320
+ return;
1321
+ }
1322
+ this.swipeEnd(ev);
1323
+ try {
1324
+ return ev.target.releasePointerCapture(ev.pointerId);
1325
+ } catch (error) {
1326
+
1327
+ }
1328
+ },
1329
+ onMouseDown: function(ev) {
1330
+ if (this.hasTouchEvents || this.hasPointerEvents) {
1331
+ return;
1332
+ }
1333
+ if (ev.which && ev.which !== 1) { // Ignore right-click
1334
+ return;
1335
+ }
1336
+ return this.swipeStart(ev);
1337
+ },
1338
+ onMouseMove: function(ev) {
1339
+ if (!(this.hasTouchEvents || this.hasPointerEvents)) {
1340
+ return this.swipeMove(ev);
1341
+ }
1342
+ },
1343
+ onMouseUp: function(ev) {
1344
+ if (!(this.hasTouchEvents || this.hasPointerEvents)) {
1345
+ return this.swipeEnd(ev);
1346
+ }
1347
+ },
1348
+ dragScroll: function(x, y) {
1349
+ this.scrollLeft = this.startScrollLeft - x;
1350
+ return this.scrollTop = this.startScrollTop - y;
1351
+ },
1352
+ onWheel: function(ev) {
1353
+ if (this.wheel === 'scroll' && this.zoom > 1 && this.dragToScroll) {
1354
+ this.scrollLeft = this.$refs.viewport.scrollLeft + ev.deltaX;
1355
+ this.scrollTop = this.$refs.viewport.scrollTop + ev.deltaY;
1356
+ if (ev.cancelable) {
1357
+ ev.preventDefault();
1358
+ }
1359
+ }
1360
+ if (this.wheel === 'zoom') {
1361
+ if (ev.deltaY >= 100) {
1362
+ this.zoomOut(ev);
1363
+ return ev.preventDefault();
1364
+ } else if (ev.deltaY <= -100) {
1365
+ this.zoomIn(ev);
1366
+ return ev.preventDefault();
1367
+ }
1368
+ }
1369
+ },
1370
+ preloadImages: function(hiRes) {
1371
+ if ( hiRes === void 0 ) hiRes = false;
1372
+
1373
+ var i, j, k, ref, ref1, ref2, ref3, src;
1374
+ for (i = j = ref = this.currentPage - 3, ref1 = this.currentPage + 3; (ref <= ref1 ? j <= ref1 : j >= ref1); i = ref <= ref1 ? ++j : --j) {
1375
+ this.pageUrlLoading(i); // this preloads image
1376
+ }
1377
+ if (hiRes) {
1378
+ for (i = k = ref2 = this.currentPage, ref3 = this.currentPage + this.displayedPages; (ref2 <= ref3 ? k < ref3 : k > ref3); i = ref2 <= ref3 ? ++k : --k) {
1379
+ src = this.pagesHiRes[i];
1380
+ if (src) {
1381
+ (new Image()).src = src;
1382
+ }
1383
+ }
1384
+ }
1385
+ },
1386
+ goToPage: function(p) {
1387
+ if (p === null || p === this.page) {
1388
+ return;
1389
+ }
1390
+ if (this.pages[0] === null) {
1391
+ if (this.displayedPages === 2 && p === 1) {
1392
+ this.currentPage = 0;
1393
+ } else {
1394
+ this.currentPage = p;
1395
+ }
1396
+ } else {
1397
+ this.currentPage = p - 1;
1398
+ }
1399
+ this.minX = 2e308;
1400
+ this.maxX = -2e308;
1401
+ return this.currentCenterOffset = this.centerOffset;
1402
+ },
1403
+ loadImage: function(url) {
1404
+ var this$1$1 = this;
1405
+
1406
+ var img;
1407
+ if (this.imageWidth === null) {
1408
+ // First loaded image defines the image width and height.
1409
+ // So it must be true image, not 'loading' image.
1410
+ return url;
1411
+ } else {
1412
+ if (this.loadedImages[url]) {
1413
+ return url;
1414
+ } else {
1415
+ img = new Image();
1416
+ img.onload = function () {
1417
+ if (this$1$1.$set) {
1418
+ return this$1$1.$set(this$1$1.loadedImages, url, true);
1419
+ } else {
1420
+ return this$1$1.loadedImages[url] = true;
1421
+ }
1422
+ };
1423
+ img.src = url;
1424
+ return this.loadingImage;
1425
+ }
1426
+ }
1427
+ }
1428
+ },
1429
+ watch: {
1430
+ currentPage: function() {
1431
+ this.firstPage = this.currentPage;
1432
+ this.secondPage = this.currentPage + 1;
1433
+ return this.preloadImages();
1434
+ },
1435
+ centerOffset: function() {
1436
+ var this$1$1 = this;
1437
+
1438
+ var animate;
1439
+ if (this.animatingCenter) {
1440
+ return;
1441
+ }
1442
+ animate = function () {
1443
+ return requestAnimationFrame(function () {
1444
+ var diff, rate;
1445
+ rate = 0.1;
1446
+ diff = this$1$1.centerOffset - this$1$1.currentCenterOffset;
1447
+ if (Math.abs(diff) < 0.5) {
1448
+ this$1$1.currentCenterOffset = this$1$1.centerOffset;
1449
+ return this$1$1.animatingCenter = false;
1450
+ } else {
1451
+ this$1$1.currentCenterOffset += diff * rate;
1452
+ return animate();
1453
+ }
1454
+ });
1455
+ };
1456
+ this.animatingCenter = true;
1457
+ return animate();
1458
+ },
1459
+ scrollLeftLimited: function(val) {
1460
+ var this$1$1 = this;
1461
+
1462
+ if (this.IE) {
1463
+ return requestAnimationFrame(function () {
1464
+ return this$1$1.$refs.viewport.scrollLeft = val;
1465
+ });
1466
+ } else {
1467
+ return this.$refs.viewport.scrollLeft = val;
1468
+ }
1469
+ },
1470
+ scrollTopLimited: function(val) {
1471
+ var this$1$1 = this;
1472
+
1473
+ if (this.IE) {
1474
+ return requestAnimationFrame(function () {
1475
+ return this$1$1.$refs.viewport.scrollTop = val;
1476
+ });
1477
+ } else {
1478
+ return this.$refs.viewport.scrollTop = val;
1479
+ }
1480
+ },
1481
+ pages: function(after, before) {
1482
+ this.fixFirstPage();
1483
+ if (!(before != null ? before.length : void 0) && (after != null ? after.length : void 0)) {
1484
+ if (this.startPage > 1 && after[0] === null) {
1485
+ return this.currentPage++;
1486
+ }
1487
+ }
1488
+ },
1489
+ startPage: function(p) {
1490
+ return this.goToPage(p);
1491
+ }
1492
+ }
1493
+ };
1494
+
1495
+ function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
1496
+ if (typeof shadowMode !== 'boolean') {
1497
+ createInjectorSSR = createInjector;
1498
+ createInjector = shadowMode;
1499
+ shadowMode = false;
1500
+ }
1501
+ // Vue.extend constructor export interop.
1502
+ var options = typeof script === 'function' ? script.options : script;
1503
+ // render functions
1504
+ if (template && template.render) {
1505
+ options.render = template.render;
1506
+ options.staticRenderFns = template.staticRenderFns;
1507
+ options._compiled = true;
1508
+ // functional template
1509
+ if (isFunctionalTemplate) {
1510
+ options.functional = true;
1511
+ }
1512
+ }
1513
+ // scopedId
1514
+ if (scopeId) {
1515
+ options._scopeId = scopeId;
1516
+ }
1517
+ var hook;
1518
+ if (moduleIdentifier) {
1519
+ // server build
1520
+ hook = function (context) {
1521
+ // 2.3 injection
1522
+ context =
1523
+ context || // cached call
1524
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
1525
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
1526
+ // 2.2 with runInNewContext: true
1527
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
1528
+ context = __VUE_SSR_CONTEXT__;
1529
+ }
1530
+ // inject component styles
1531
+ if (style) {
1532
+ style.call(this, createInjectorSSR(context));
1533
+ }
1534
+ // register component module identifier for async chunk inference
1535
+ if (context && context._registeredComponents) {
1536
+ context._registeredComponents.add(moduleIdentifier);
1537
+ }
1538
+ };
1539
+ // used by ssr in case component is cached and beforeCreate
1540
+ // never gets called
1541
+ options._ssrRegister = hook;
1542
+ }
1543
+ else if (style) {
1544
+ hook = shadowMode
1545
+ ? function (context) {
1546
+ style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
1547
+ }
1548
+ : function (context) {
1549
+ style.call(this, createInjector(context));
1550
+ };
1551
+ }
1552
+ if (hook) {
1553
+ if (options.functional) {
1554
+ // register for functional component in vue file
1555
+ var originalRender = options.render;
1556
+ options.render = function renderWithStyleInjection(h, context) {
1557
+ hook.call(context);
1558
+ return originalRender(h, context);
1559
+ };
1560
+ }
1561
+ else {
1562
+ // inject component registration as beforeCreate hook
1563
+ var existing = options.beforeCreate;
1564
+ options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
1565
+ }
1566
+ }
1567
+ return script;
1568
+ }
1569
+
1570
+ var isOldIE = typeof navigator !== 'undefined' &&
1571
+ /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
1572
+ function createInjector(context) {
1573
+ return function (id, style) { return addStyle(id, style); };
1574
+ }
1575
+ var HEAD;
1576
+ var styles = {};
1577
+ function addStyle(id, css) {
1578
+ var group = isOldIE ? css.media || 'default' : id;
1579
+ var style = styles[group] || (styles[group] = { ids: new Set(), styles: [] });
1580
+ if (!style.ids.has(id)) {
1581
+ style.ids.add(id);
1582
+ var code = css.source;
1583
+ if (css.map) {
1584
+ // https://developer.chrome.com/devtools/docs/javascript-debugging
1585
+ // this makes source maps inside style tags work properly in Chrome
1586
+ code += '\n/*# sourceURL=' + css.map.sources[0] + ' */';
1587
+ // http://stackoverflow.com/a/26603875
1588
+ code +=
1589
+ '\n/*# sourceMappingURL=data:application/json;base64,' +
1590
+ btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) +
1591
+ ' */';
1592
+ }
1593
+ if (!style.element) {
1594
+ style.element = document.createElement('style');
1595
+ style.element.type = 'text/css';
1596
+ if (css.media)
1597
+ { style.element.setAttribute('media', css.media); }
1598
+ if (HEAD === undefined) {
1599
+ HEAD = document.head || document.getElementsByTagName('head')[0];
1600
+ }
1601
+ HEAD.appendChild(style.element);
1602
+ }
1603
+ if ('styleSheet' in style.element) {
1604
+ style.styles.push(code);
1605
+ style.element.styleSheet.cssText = style.styles
1606
+ .filter(Boolean)
1607
+ .join('\n');
1608
+ }
1609
+ else {
1610
+ var index = style.ids.size - 1;
1611
+ var textNode = document.createTextNode(code);
1612
+ var nodes = style.element.childNodes;
1613
+ if (nodes[index])
1614
+ { style.element.removeChild(nodes[index]); }
1615
+ if (nodes.length)
1616
+ { style.element.insertBefore(textNode, nodes[index]); }
1617
+ else
1618
+ { style.element.appendChild(textNode); }
1619
+ }
1620
+ }
1621
+ }
1622
+
1623
+ /* script */
1624
+ var __vue_script__ = script;
1625
+
1626
+ /* template */
1627
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_vm._t("default",null,null,{
1628
+ canFlipLeft: _vm.canFlipLeft,
1629
+ canFlipRight: _vm.canFlipRight,
1630
+ canZoomIn: _vm.canZoomIn,
1631
+ canZoomOut: _vm.canZoomOut,
1632
+ page: _vm.page,
1633
+ numPages: _vm.numPages,
1634
+ flipLeft: _vm.flipLeft,
1635
+ flipRight: _vm.flipRight,
1636
+ zoomIn: _vm.zoomIn,
1637
+ zoomOut: _vm.zoomOut,
1638
+ }),_vm._v(" "),_c('div',{ref:"viewport",staticClass:"viewport",class:{
1639
+ zoom: _vm.zooming || _vm.zoom > 1,
1640
+ 'drag-to-scroll': _vm.dragToScroll,
1641
+ },style:({ cursor: _vm.cursor == 'grabbing' ? 'grabbing' : 'auto' }),on:{"touchmove":_vm.onTouchMove,"pointermove":_vm.onPointerMove,"mousemove":_vm.onMouseMove,"touchend":_vm.onTouchEnd,"touchcancel":_vm.onTouchEnd,"pointerup":_vm.onPointerUp,"pointercancel":_vm.onPointerUp,"mouseup":_vm.onMouseUp,"wheel":_vm.onWheel}},[_c('div',{staticClass:"flipbook-container",style:({ transform: ("scale(" + _vm.zoom + ")") })},[_c('div',{staticClass:"click-to-flip left",style:({ cursor: _vm.canFlipLeft ? 'pointer' : 'auto' }),on:{"click":_vm.flipLeft}}),_vm._v(" "),_c('div',{staticClass:"click-to-flip right",style:({ cursor: _vm.canFlipRight ? 'pointer' : 'auto' }),on:{"click":_vm.flipRight}}),_vm._v(" "),_c('div',{style:({ transform: ("translateX(" + _vm.centerOffsetSmoothed + "px)") })},[(_vm.showLeftPage)?_c('img',{staticClass:"page fixed",style:({
1642
+ width: _vm.pageWidth + 'px',
1643
+ height: _vm.pageHeight + 'px',
1644
+ left: _vm.xMargin + 'px',
1645
+ top: _vm.yMargin + 'px',
1646
+ }),attrs:{"src":_vm.pageUrlLoading(_vm.leftPage, true)},on:{"load":function($event){return _vm.didLoadImage($event)}}}):_vm._e(),_vm._v(" "),(_vm.showRightPage)?_c('img',{staticClass:"page fixed",style:({
1647
+ width: _vm.pageWidth + 'px',
1648
+ height: _vm.pageHeight + 'px',
1649
+ left: _vm.viewWidth / 2 + 'px',
1650
+ top: _vm.yMargin + 'px',
1651
+ }),attrs:{"src":_vm.pageUrlLoading(_vm.rightPage, true)},on:{"load":function($event){return _vm.didLoadImage($event)}}}):_vm._e(),_vm._v(" "),_c('div',{style:({ opacity: _vm.flip.opacity })},_vm._l((_vm.polygonArray),function(ref){
1652
+ var key = ref[0];
1653
+ var bgImage = ref[1];
1654
+ var lighting = ref[2];
1655
+ var bgPos = ref[3];
1656
+ var transform = ref[4];
1657
+ var z = ref[5];
1658
+ return _c('div',{key:key,staticClass:"polygon",class:{ blank: !bgImage },style:({
1659
+ backgroundImage: bgImage && ("url(" + (_vm.loadImage(bgImage)) + ")"),
1660
+ backgroundSize: _vm.polygonBgSize,
1661
+ backgroundPosition: bgPos,
1662
+ width: _vm.polygonWidth,
1663
+ height: _vm.polygonHeight,
1664
+ transform: transform,
1665
+ zIndex: z,
1666
+ })},[_c('div',{directives:[{name:"show",rawName:"v-show",value:(lighting.length),expression:"lighting.length"}],staticClass:"lighting",style:({ backgroundImage: lighting })})])}),0),_vm._v(" "),_c('div',{staticClass:"bounding-box",style:({
1667
+ left: _vm.boundingLeft + 'px',
1668
+ top: _vm.yMargin + 'px',
1669
+ width: _vm.boundingRight - _vm.boundingLeft + 'px',
1670
+ height: _vm.pageHeight + 'px',
1671
+ cursor: _vm.cursor,
1672
+ }),on:{"touchstart":_vm.onTouchStart,"pointerdown":_vm.onPointerDown,"mousedown":_vm.onMouseDown}})])])])],2)};
1673
+ var __vue_staticRenderFns__ = [];
1674
+
1675
+ /* style */
1676
+ var __vue_inject_styles__ = function (inject) {
1677
+ if (!inject) { return }
1678
+ inject("data-v-e3f0fbe2_0", { source: ".viewport[data-v-e3f0fbe2]{-webkit-overflow-scrolling:touch;width:100%;height:100%}.viewport.zoom[data-v-e3f0fbe2]{overflow:scroll}.viewport.zoom.drag-to-scroll[data-v-e3f0fbe2]{overflow:hidden}.flipbook-container[data-v-e3f0fbe2]{position:relative;width:100%;height:100%;transform-origin:top left;user-select:none}.click-to-flip[data-v-e3f0fbe2]{position:absolute;width:50%;height:100%;top:0;user-select:none}.click-to-flip.left[data-v-e3f0fbe2]{left:0}.click-to-flip.right[data-v-e3f0fbe2]{right:0}.bounding-box[data-v-e3f0fbe2]{position:absolute;user-select:none}.page[data-v-e3f0fbe2]{position:absolute;backface-visibility:hidden}.polygon[data-v-e3f0fbe2]{position:absolute;top:0;left:0;background-repeat:no-repeat;backface-visibility:hidden;transform-origin:center left}.polygon.blank[data-v-e3f0fbe2]{background-color:#ddd}.polygon .lighting[data-v-e3f0fbe2]{width:100%;height:100%}", map: undefined, media: undefined });
1679
+
1680
+ };
1681
+ /* scoped */
1682
+ var __vue_scope_id__ = "data-v-e3f0fbe2";
1683
+ /* module identifier */
1684
+ var __vue_module_identifier__ = undefined;
1685
+ /* functional template */
1686
+ var __vue_is_functional_template__ = false;
1687
+ /* style inject SSR */
1688
+
1689
+ /* style inject shadow dom */
1690
+
1691
+
1692
+
1693
+ var __vue_component__ = /*#__PURE__*/normalizeComponent(
1694
+ { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
1695
+ __vue_inject_styles__,
1696
+ __vue_script__,
1697
+ __vue_scope_id__,
1698
+ __vue_is_functional_template__,
1699
+ __vue_module_identifier__,
1700
+ false,
1701
+ createInjector,
1702
+ undefined,
1703
+ undefined
1704
+ );
1705
+
1706
+
1707
+
1708
+ ;// ./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/BookCatalogueDrawer.vue?vue&type=template&id=3930be62&scoped=true
1709
+ var BookCatalogueDrawervue_type_template_id_3930be62_scoped_true_render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:"catalogue-drawer-container"},[(_vm.visible)?_c('div',{staticClass:"drawer-overlay",on:{"click":_vm.closeDrawer}}):_vm._e(),_c('div',{staticClass:"catalogue-drawer",class:{ 'drawer-open': _vm.visible },style:({ width: _vm.drawerWidth })},[_c('div',{staticClass:"drawer-header"},[_c('h3',{staticClass:"drawer-title"},[_vm._v("目录")]),_c('button',{staticClass:"close-button",on:{"click":_vm.closeDrawer}},[_c('span',{staticClass:"close-icon"},[_vm._v("×")])])]),_c('div',{staticClass:"page-jump-section"},[_c('input',{directives:[{name:"model",rawName:"v-model",value:(_vm.jumpPageInput),expression:"jumpPageInput"}],staticClass:"page-jump-input",attrs:{"type":"text","placeholder":"请输入页码"},domProps:{"value":(_vm.jumpPageInput)},on:{"input":[function($event){if($event.target.composing)return;_vm.jumpPageInput=$event.target.value},_vm.handlePageInput],"focus":_vm.onInputFocus,"blur":_vm.onInputBlur}}),_c('button',{staticClass:"btn-jump",on:{"click":_vm.handleJumpToPage}},[_vm._v(" 跳转 ")])]),_c('div',{staticClass:"drawer-content"},[(_vm.loading)?_c('div',{staticClass:"loading-container"},[_c('div',{staticClass:"loading-spinner"}),_c('p',[_vm._v("加载目录中...")])]):(_vm.error)?_c('div',{staticClass:"error-container"},[_c('div',{staticClass:"error-icon"},[_vm._v("⚠️")]),_c('p',[_vm._v("目录加载失败")]),_c('button',{staticClass:"retry-button",on:{"click":_vm.fetchCatalogue}},[_vm._v(" 重新加载 ")])]):(_vm.catalogueData && _vm.catalogueData.length > 0)?_c('div',{staticClass:"catalogue-list"},_vm._l((_vm.catalogueData),function(item,index){return _c('catalogue-item',{key:`catalogue-${index}`,attrs:{"item":item || {},"level":0},on:{"item-click":_vm.onItemClick}})}),1):_c('div',{staticClass:"empty-container"},[_c('p',[_vm._v("暂无目录")])])])])])
1710
+ }
1711
+ var BookCatalogueDrawervue_type_template_id_3930be62_scoped_true_staticRenderFns = []
1712
+
1713
+
1714
+ ;// ./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/BookCatalogueDrawer.vue?vue&type=script&lang=js
1715
+
1716
+ // 目录项组件
1717
+ const CatalogueItem = {
1718
+ name: 'CatalogueItem',
1719
+ props: {
1720
+ item: {
1721
+ type: Object,
1722
+ required: true
1723
+ },
1724
+ level: {
1725
+ type: Number,
1726
+ default: 0
1727
+ }
1728
+ },
1729
+ data() {
1730
+ return {
1731
+ expanded: false
1732
+ }
1733
+ },
1734
+ computed: {
1735
+ hasChildren() {
1736
+ const children = this.item.childrenList || this.item.children || this.item.subItems || this.item.items
1737
+ return children && children.length > 0
1738
+ },
1739
+ childrenData() {
1740
+ return this.item.childrenList || this.item.children || this.item.subItems || this.item.items || []
1741
+ },
1742
+ itemStyle() {
1743
+ // 移除缩进,所有层级都左对齐
1744
+ return {
1745
+ paddingLeft: '12px',
1746
+ paddingRight: '12px'
1747
+ }
1748
+ },
1749
+ levelClass() {
1750
+ return `level-${this.level}`
1751
+ }
1752
+ },
1753
+ methods: {
1754
+ toggleExpand() {
1755
+ if (this.hasChildren) {
1756
+ this.expanded = !this.expanded
1757
+ } else {
1758
+ this.handleClick()
1759
+ }
1760
+ },
1761
+ handleClick() {
1762
+ this.$emit('item-click', this.item)
1763
+ }
1764
+ },
1765
+ render(h) {
1766
+ const item = this.item
1767
+ const titleText = item.titleName || item.title || item.name || item.text || item.label || '未命名章节'
1768
+ const pageNum = item.startPageNum || item.pageNumber || item.page || item.pageNum
1769
+
1770
+ // 创建拖拽手柄
1771
+ const dragHandle = h('span', {
1772
+ class: 'drag-handle'
1773
+ }, '')
1774
+
1775
+ // 创建展开图标
1776
+ const expandIcon = this.hasChildren ? h('span', {
1777
+ class: 'expand-icon'
1778
+ }, this.expanded ? '▼' : '▶') : null
1779
+
1780
+ // 创建层级指示器
1781
+ const levelIndicator = this.level > 0 ? h('span', {
1782
+ class: `level-indicator level-${this.level}`
1783
+ }, '•'.repeat(this.level)) : null
1784
+
1785
+ // 创建标题
1786
+ const titleSpan = h('span', {
1787
+ class: 'item-title'
1788
+ }, titleText)
1789
+
1790
+ // 创建页码(放在标题后面)
1791
+ // const pageSpan = pageNum ? h('span', {
1792
+ // class: 'page-number'
1793
+ // }, `第${pageNum}页`) : null
1794
+ const pageSpan = null
1795
+ // 创建子级目录
1796
+ const childrenDiv = (this.hasChildren && this.expanded) ? h('div', {
1797
+ class: 'children-container'
1798
+ }, this.childrenData.map((child, index) => {
1799
+ return h('catalogue-item', {
1800
+ key: index,
1801
+ props: {
1802
+ item: child,
1803
+ level: this.level + 1
1804
+ },
1805
+ on: {
1806
+ 'item-click': (item) => this.$emit('item-click', item)
1807
+ }
1808
+ })
1809
+ })) : null
1810
+
1811
+ return h('div', {
1812
+ class: 'catalogue-item-wrapper'
1813
+ }, [
1814
+ h('div', {
1815
+ class: [
1816
+ 'catalogue-item',
1817
+ this.levelClass,
1818
+ {
1819
+ 'has-children': this.hasChildren,
1820
+ 'expanded': this.expanded
1821
+ }
1822
+ ],
1823
+ style: this.itemStyle,
1824
+ on: {
1825
+ click: this.toggleExpand
1826
+ }
1827
+ }, [
1828
+ h('div', {
1829
+ class: 'item-content'
1830
+ }, [dragHandle, expandIcon, levelIndicator, titleSpan, pageSpan].filter(Boolean))
1831
+ ]),
1832
+ childrenDiv
1833
+ ].filter(Boolean))
1834
+ }
1835
+ }
1836
+
1837
+ /* harmony default export */ var BookCatalogueDrawervue_type_script_lang_js = ({
1838
+ name: 'BookCatalogueDrawer',
1839
+ components: {
1840
+ CatalogueItem
1841
+ },
1842
+ props: {
1843
+ value: {
1844
+ type: Boolean,
1845
+ default: false
1846
+ },
1847
+ bookId: {
1848
+ type: String,
1849
+ default: ''
1850
+ },
1851
+ catalogue: {
1852
+ type: Array,
1853
+ default: () => []
1854
+ },
1855
+ loading: {
1856
+ type: Boolean,
1857
+ default: false
1858
+ }
1859
+ },
1860
+ data() {
1861
+ return {
1862
+ catalogueData: [],
1863
+ error: null,
1864
+ jumpPageInput: ''
1865
+ }
1866
+ },
1867
+ computed: {
1868
+ visible: {
1869
+ get() {
1870
+ return this.value
1871
+ },
1872
+ set(val) {
1873
+ this.$emit('input', val)
1874
+ }
1875
+ },
1876
+ drawerWidth() {
1877
+ // 响应式宽度
1878
+ return window.innerWidth <= 768 ? '80%' : '400px'
1879
+ }
1880
+ },
1881
+ watch: {
1882
+ visible(newVal) {
1883
+ if (newVal && this.bookId && !this.catalogueData.length) {
1884
+ this.$emit('fetch-catalogue', this.bookId)
1885
+ }
1886
+ },
1887
+ bookId(newVal) {
1888
+ if (newVal && this.visible) {
1889
+ this.$emit('fetch-catalogue', newVal)
1890
+ }
1891
+ },
1892
+ catalogue: {
1893
+ handler(newVal) {
1894
+ if (newVal && newVal.length > 0) {
1895
+ this.catalogueData = this.processCatalogueData(newVal)
1896
+ }
1897
+ },
1898
+ immediate: true
1899
+ }
1900
+ },
1901
+ methods: {
1902
+ /**
1903
+ * 获取目录数据 - 触发事件让父组件处理
1904
+ */
1905
+ fetchCatalogue() {
1906
+ if (!this.bookId) {
1907
+ console.warn('缺少 bookId,无法获取目录')
1908
+ return
1909
+ }
1910
+ this.$emit('fetch-catalogue', this.bookId)
1911
+ },
1912
+
1913
+ /**
1914
+ * 处理目录数据,确保数据结构正确
1915
+ * @param {Array} data - 原始目录数据
1916
+ * @returns {Array} 处理后的目录数据
1917
+ */
1918
+ processCatalogueData(data) {
1919
+ if (!Array.isArray(data)) {
1920
+ return []
1921
+ }
1922
+
1923
+ return data.map(item => {
1924
+ if (!item || typeof item !== 'object') {
1925
+ return {
1926
+ titleName: '未知章节',
1927
+ startPageNum: null,
1928
+ childrenList: []
1929
+ }
1930
+ }
1931
+
1932
+ // 确保必要的字段存在
1933
+ const processedItem = {
1934
+ ...item,
1935
+ titleName: item.titleName || item.title || item.name || '未命名章节',
1936
+ startPageNum: item.startPageNum || item.pageNumber || item.page || item.pageNum || null,
1937
+ childrenList: item.childrenList || item.children || item.subItems || item.items || []
1938
+ }
1939
+
1940
+ // 递归处理子级
1941
+ if (processedItem.childrenList && processedItem.childrenList.length > 0) {
1942
+ processedItem.childrenList = this.processCatalogueData(processedItem.childrenList)
1943
+ }
1944
+
1945
+ return processedItem
1946
+ })
1947
+ },
1948
+
1949
+ /**
1950
+ * 目录项点击事件
1951
+ * @param {Object} item - 点击的目录项
1952
+ */
1953
+ onItemClick(item) {
1954
+ console.log('目录项被点击:', item)
1955
+
1956
+ // 发送事件给父组件
1957
+ this.$emit('catalogue-click', item)
1958
+
1959
+ // 如果有页码信息,可以进行跳转
1960
+ const pageNumber = item.startPageNum || item.pageNumber || item.page || item.pageNum
1961
+ if (pageNumber) {
1962
+ this.$emit('page-jump', pageNumber)
1963
+ }
1964
+ },
1965
+
1966
+ /**
1967
+ * 关闭抽屉
1968
+ */
1969
+ closeDrawer() {
1970
+ this.$emit('input', false)
1971
+ },
1972
+
1973
+ /**
1974
+ * 处理页码输入
1975
+ */
1976
+ handlePageInput(e) {
1977
+ const value = e.target.value
1978
+ const numValue = value.replace(/[^\d]/g, '')
1979
+ this.jumpPageInput = numValue
1980
+ },
1981
+
1982
+ /**
1983
+ * 执行页码跳转
1984
+ */
1985
+ handleJumpToPage() {
1986
+ const pageNum = parseInt(this.jumpPageInput)
1987
+ if (pageNum && pageNum >= 1) {
1988
+ this.$emit('page-jump', pageNum)
1989
+ this.jumpPageInput = ''
1990
+ this.closeDrawer()
1991
+ }
1992
+ },
1993
+
1994
+ /**
1995
+ * 输入框获得焦点
1996
+ */
1997
+ onInputFocus() {
1998
+ // 可以在这里添加焦点处理逻辑
1999
+ },
2000
+
2001
+ /**
2002
+ * 输入框失去焦点
2003
+ */
2004
+ onInputBlur() {
2005
+ this.$emit('Focus')
2006
+ },
2007
+
2008
+ /**
2009
+ * 重置数据
2010
+ */
2011
+ resetData() {
2012
+ this.catalogueData = []
2013
+ this.error = null
2014
+ this.loading = false
2015
+ },
2016
+
2017
+ /**
2018
+ * 处理窗口大小变化
2019
+ */
2020
+ handleResize() {
2021
+ // 可以在这里添加响应式逻辑
2022
+ }
2023
+ },
2024
+
2025
+ mounted() {
2026
+ // 监听窗口大小变化
2027
+ window.addEventListener('resize', this.handleResize)
2028
+ },
2029
+
2030
+ beforeDestroy() {
2031
+ window.removeEventListener('resize', this.handleResize)
2032
+ }
2033
+ });
2034
+
2035
+ ;// ./src/components/BookCatalogueDrawer.vue?vue&type=script&lang=js
2036
+ /* harmony default export */ var components_BookCatalogueDrawervue_type_script_lang_js = (BookCatalogueDrawervue_type_script_lang_js);
2037
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-52.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-52.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-52.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/BookCatalogueDrawer.vue?vue&type=style&index=0&id=3930be62&prod&scoped=true&lang=css
2038
+ // extracted by mini-css-extract-plugin
2039
+
2040
+ ;// ./src/components/BookCatalogueDrawer.vue?vue&type=style&index=0&id=3930be62&prod&scoped=true&lang=css
2041
+
2042
+ ;// ./node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js
2043
+ /* globals __VUE_SSR_CONTEXT__ */
2044
+
2045
+ // IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
2046
+ // This module is a runtime utility for cleaner component module output and will
2047
+ // be included in the final webpack user bundle.
2048
+
2049
+ function componentNormalizer_normalizeComponent(
2050
+ scriptExports,
2051
+ render,
2052
+ staticRenderFns,
2053
+ functionalTemplate,
2054
+ injectStyles,
2055
+ scopeId,
2056
+ moduleIdentifier /* server only */,
2057
+ shadowMode /* vue-cli only */
2058
+ ) {
2059
+ // Vue.extend constructor export interop
2060
+ var options =
2061
+ typeof scriptExports === 'function' ? scriptExports.options : scriptExports
2062
+
2063
+ // render functions
2064
+ if (render) {
2065
+ options.render = render
2066
+ options.staticRenderFns = staticRenderFns
2067
+ options._compiled = true
2068
+ }
2069
+
2070
+ // functional template
2071
+ if (functionalTemplate) {
2072
+ options.functional = true
2073
+ }
2074
+
2075
+ // scopedId
2076
+ if (scopeId) {
2077
+ options._scopeId = 'data-v-' + scopeId
2078
+ }
2079
+
2080
+ var hook
2081
+ if (moduleIdentifier) {
2082
+ // server build
2083
+ hook = function (context) {
2084
+ // 2.3 injection
2085
+ context =
2086
+ context || // cached call
2087
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
2088
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
2089
+ // 2.2 with runInNewContext: true
2090
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
2091
+ context = __VUE_SSR_CONTEXT__
2092
+ }
2093
+ // inject component styles
2094
+ if (injectStyles) {
2095
+ injectStyles.call(this, context)
2096
+ }
2097
+ // register component module identifier for async chunk inferrence
2098
+ if (context && context._registeredComponents) {
2099
+ context._registeredComponents.add(moduleIdentifier)
2100
+ }
2101
+ }
2102
+ // used by ssr in case component is cached and beforeCreate
2103
+ // never gets called
2104
+ options._ssrRegister = hook
2105
+ } else if (injectStyles) {
2106
+ hook = shadowMode
2107
+ ? function () {
2108
+ injectStyles.call(
2109
+ this,
2110
+ (options.functional ? this.parent : this).$root.$options.shadowRoot
2111
+ )
2112
+ }
2113
+ : injectStyles
2114
+ }
2115
+
2116
+ if (hook) {
2117
+ if (options.functional) {
2118
+ // for template-only hot-reload because in that case the render fn doesn't
2119
+ // go through the normalizer
2120
+ options._injectStyles = hook
2121
+ // register for functional component in vue file
2122
+ var originalRender = options.render
2123
+ options.render = function renderWithStyleInjection(h, context) {
2124
+ hook.call(context)
2125
+ return originalRender(h, context)
2126
+ }
2127
+ } else {
2128
+ // inject component registration as beforeCreate hook
2129
+ var existing = options.beforeCreate
2130
+ options.beforeCreate = existing ? [].concat(existing, hook) : [hook]
2131
+ }
2132
+ }
2133
+
2134
+ return {
2135
+ exports: scriptExports,
2136
+ options: options
2137
+ }
2138
+ }
2139
+
2140
+ ;// ./src/components/BookCatalogueDrawer.vue
2141
+
2142
+
2143
+
2144
+ ;
2145
+
2146
+
2147
+ /* normalize component */
2148
+
2149
+ var component = componentNormalizer_normalizeComponent(
2150
+ components_BookCatalogueDrawervue_type_script_lang_js,
2151
+ BookCatalogueDrawervue_type_template_id_3930be62_scoped_true_render,
2152
+ BookCatalogueDrawervue_type_template_id_3930be62_scoped_true_staticRenderFns,
2153
+ false,
2154
+ null,
2155
+ "3930be62",
2156
+ null
2157
+
2158
+ )
2159
+
2160
+ /* harmony default export */ var BookCatalogueDrawer = (component.exports);
2161
+ ;// ./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/BookReader.vue?vue&type=script&lang=js
2162
+
2163
+
2164
+
2165
+
2166
+ /* harmony default export */ var BookReadervue_type_script_lang_js = ({
2167
+ name: 'PhotoAlbumView',
2168
+ components: {
2169
+ Flipbook: __vue_component__,
2170
+ BookCatalogueDrawer: BookCatalogueDrawer
2171
+ },
2172
+ props: {
2173
+ pages: {
2174
+ type: Array,
2175
+ default: () => []
2176
+ },
2177
+ bookId: {
2178
+ type: String,
2179
+ default: ''
2180
+ },
2181
+ startPage: {
2182
+ type: Number,
2183
+ default: 1
2184
+ },
2185
+ catalogue: {
2186
+ type: Array,
2187
+ default: () => []
2188
+ },
2189
+ catalogueLoading: {
2190
+ type: Boolean,
2191
+ default: false
2192
+ }
2193
+ },
2194
+ data() {
2195
+ return {
2196
+ currentPage: 1,
2197
+ flag: true,
2198
+ // 设备检测
2199
+ isMobile: false,
2200
+ // 接口相关数据
2201
+ booksData: null,
2202
+ loading: false,
2203
+ error: null,
2204
+ showSuccessToast: false,
2205
+ // 内容就绪状态
2206
+ contentReady: false,
2207
+ // 手势缩放相关
2208
+ zoomScale: 1,
2209
+ translateX: 0,
2210
+ translateY: 0,
2211
+ lastTouchDistance: 0,
2212
+ lastTouchCenter: { x: 0, y: 0 },
2213
+ isZooming: false,
2214
+ isPanning: false,
2215
+ touchStartTime: 0,
2216
+ initialTouches: [],
2217
+ // Flipbook区域双击检测
2218
+ flipbookTouchStartTime: 0,
2219
+ flipbookLastTapTime: 0,
2220
+ // 目录相关
2221
+ showCatalogueDrawer: false,
2222
+ // 目录按钮拖拽相关
2223
+ catalogueButtonDragging: false,
2224
+ catalogueButtonPosition: { x: 20, y: 20 },
2225
+ dragStartPosition: { x: 0, y: 0 },
2226
+ dragOffset: { x: 0, y: 0 },
2227
+ // 翻页模式相关
2228
+ flipMode: 'flip', // flip: 仿真翻页, slide: 滑动翻页, fade: 淡入淡出, scroll: 垂直滚动
2229
+ showFlipModeMenu: false,
2230
+ flipModes: [
2231
+ { value: 'flip', label: '仿真翻页', icon: '📖' },
2232
+ { value: 'slide', label: '滑动翻页', icon: '↔️' },
2233
+ { value: 'fade', label: '淡入淡出', icon: '✨' },
2234
+ { value: 'scroll', label: '垂直滚动', icon: '📜' },
2235
+ { value: 'clip', label: '截断特效', icon: '✂️' },
2236
+ { value: 'card', label: '卡片风格', icon: '🃏' }
2237
+ ],
2238
+ // 滑动模式相关
2239
+ slideStartX: 0,
2240
+ slideCurrentX: 0,
2241
+ slideIsDragging: false,
2242
+ // URL参数控制
2243
+ flipModeFromUrl: false, // 翻页模式是否由URL参数指定
2244
+ // 控件自动隐藏相关
2245
+ showControls: false,
2246
+ hideControlsTimer: null,
2247
+ // 页码跳转相关
2248
+ jumpPageInput: ''
2249
+ }
2250
+ },
2251
+ computed: {
2252
+ totalPages() {
2253
+ return this.pages.length
2254
+ },
2255
+ pagesHiRes() {
2256
+ return this.pages
2257
+ },
2258
+ /**
2259
+ * 翻页模式图标
2260
+ */
2261
+ flipModeIcon() {
2262
+ const mode = this.flipModes.find(m => m.value === this.flipMode)
2263
+ return mode ? mode.icon : '📖'
2264
+ },
2265
+ /**
2266
+ * 翻页模式标签
2267
+ */
2268
+ flipModeLabel() {
2269
+ const mode = this.flipModes.find(m => m.value === this.flipMode)
2270
+ return mode ? mode.label : '仿真翻页'
2271
+ },
2272
+ /**
2273
+ * 滑动容器样式
2274
+ */
2275
+ slideContainerStyle() {
2276
+ const offset = -(this.currentPage - 1) * 100
2277
+ const dragOffset = this.slideIsDragging ? (this.slideCurrentX - this.slideStartX) / 5 : 0
2278
+ return {
2279
+ transform: `translateX(calc(${offset}% + ${dragOffset}px))`,
2280
+ transition: this.slideIsDragging ? 'none' : 'transform 0.3s ease-out'
2281
+ }
2282
+ },
2283
+ /**
2284
+ * 是否显示翻页模式选择器
2285
+ */
2286
+ showFlipModeSelector() {
2287
+ // 如果翻页模式是由URL参数指定的,则隐藏选择器
2288
+ return !this.flipModeFromUrl
2289
+ },
2290
+ /**
2291
+ * 卡片模式可见卡片
2292
+ */
2293
+ visibleCards() {
2294
+ const cards = []
2295
+ // 上一页
2296
+ if (this.currentPage > 1) {
2297
+ cards.push({
2298
+ src: this.pages[this.currentPage - 2],
2299
+ originalIndex: this.currentPage - 2,
2300
+ position: 'prev'
2301
+ })
2302
+ }
2303
+ // 当前页
2304
+ cards.push({
2305
+ src: this.pages[this.currentPage - 1],
2306
+ originalIndex: this.currentPage - 1,
2307
+ position: 'current'
2308
+ })
2309
+ // 下一页
2310
+ if (this.currentPage < this.totalPages) {
2311
+ cards.push({
2312
+ src: this.pages[this.currentPage],
2313
+ originalIndex: this.currentPage,
2314
+ position: 'next'
2315
+ })
2316
+ }
2317
+ return cards
2318
+ },
2319
+ /**
2320
+ * 计算当前页面显示文本
2321
+ */
2322
+ pageDisplayText() {
2323
+ if (this.totalPages === 0) return '加载中...'
2324
+ if (this.currentPage === 1 && this.totalPages > 1) return '封面'
2325
+ if (this.currentPage === this.totalPages && this.totalPages > 1) return '封底'
2326
+
2327
+ if (this.isMobile) {
2328
+ if (this.totalPages <= 2) return `第 ${this.currentPage} 页 / 共 ${this.totalPages} 页`
2329
+ return `第 ${Math.max(1, this.currentPage - 1)} 页 / 共 ${Math.max(0, this.totalPages - 2)} 页`
2330
+ } else {
2331
+ if (this.totalPages <= 2) return `第 ${this.currentPage} 页 / 共 ${this.totalPages} 页`
2332
+ return `第 ${Math.ceil((this.currentPage - 1) / 2)} 组 / 共 ${Math.ceil((this.totalPages - 2) / 2)} 组`
2333
+ }
2334
+ }
2335
+ },
2336
+ methods: {
2337
+ /**
2338
+ * 获取书籍数据
2339
+ */
2340
+ async fetchBooksData() {
2341
+ try {
2342
+ this.loading = true
2343
+ this.error = null
2344
+
2345
+ // 注释:原来从URL参数获取fileManagementId,现在改为通过props传入
2346
+ // const fileManagementId = this.$route.params.id || this.$route.query.id || ''
2347
+ // this.bookId = fileManagementId
2348
+
2349
+ // 注释:原来调用API获取数据,现在改为通过props传入
2350
+ // const response = await booksApi.getBooksSlice(fileManagementId, textContent, 1, 9999)
2351
+
2352
+ // 触发事件让父组件处理数据获取
2353
+ this.$emit('fetch-books-data', this.bookId)
2354
+
2355
+ // 如果通过props传入了pages数据,直接使用
2356
+ if (this.pages && this.pages.length > 0) {
2357
+ this.booksData = { data: { records: this.pages.map(url => ({ imageUrl: url })) } }
2358
+
2359
+ // 显示成功提示
2360
+ this.showSuccessToast = true
2361
+ setTimeout(() => {
2362
+ this.showSuccessToast = false
2363
+ }, 3000)
2364
+
2365
+ // 检查URL参数并跳转到指定页码
2366
+ this.checkUrlPageParameter()
2367
+ }
2368
+
2369
+ } catch (error) {
2370
+ console.error('获取书籍数据失败:', error)
2371
+ this.error = error
2372
+
2373
+ // 显示错误信息
2374
+ if (error.response) {
2375
+ console.error('API错误响应:', error.response.data)
2376
+ } else if (error.request) {
2377
+ console.error('网络请求失败:', error.request)
2378
+ } else {
2379
+ console.error('请求配置错误:', error.message)
2380
+ }
2381
+ } finally {
2382
+ this.loading = false
2383
+ }
2384
+ },
2385
+
2386
+ /**
2387
+ * 根据API数据更新页面
2388
+ * @param {Array} apiData - API返回的数据
2389
+ */
2390
+ updatePagesFromApiData(apiData) {
2391
+ if (!Array.isArray(apiData)) {
2392
+ console.warn('API数据格式不正确,期望数组格式')
2393
+ return
2394
+ }
2395
+
2396
+ console.log('开始更新页面数据,数据长度:', apiData.length)
2397
+
2398
+ // 这里可以根据实际的API数据结构来处理
2399
+ // 假设API返回的数据包含图片URL
2400
+ const newPages = [null] // 保留封面页
2401
+
2402
+ apiData.forEach((item, index) => {
2403
+ if (item.imageUrl) {
2404
+ newPages.push(item.imageUrl)
2405
+ console.log(`添加页面 ${index + 1}:`, item.imageUrl)
2406
+ }
2407
+ })
2408
+
2409
+ if (newPages.length > 1) {
2410
+ this.pages = newPages
2411
+ console.log('页面数据更新完成,总页数:', this.pages.length)
2412
+ }
2413
+ },
2414
+
2415
+ /**
2416
+ * 检测是否为移动设备
2417
+ */
2418
+ detectMobile() {
2419
+ const userAgent = navigator.userAgent.toLowerCase()
2420
+ const mobileKeywords = ['mobile', 'android', 'iphone', 'ipad', 'ipod', 'blackberry', 'windows phone']
2421
+
2422
+ // 检测 User Agent
2423
+ const isMobileUA = mobileKeywords.some(keyword => userAgent.includes(keyword))
2424
+
2425
+ // 检测屏幕尺寸
2426
+ const isMobileScreen = window.innerWidth <= 768
2427
+
2428
+ // 检测触摸支持
2429
+ const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0
2430
+
2431
+ // 综合判断
2432
+ this.isMobile = isMobileUA || (isMobileScreen && isTouchDevice)
2433
+
2434
+ console.log('设备检测结果:', {
2435
+ userAgent: isMobileUA,
2436
+ screenSize: isMobileScreen,
2437
+ touchSupport: isTouchDevice,
2438
+ finalResult: this.isMobile
2439
+ })
2440
+ },
2441
+
2442
+ /**
2443
+ * 预加载首页图片
2444
+ */
2445
+ async preloadFirstPage() {
2446
+ if (!this.pages || this.pages.length === 0) {
2447
+ this.contentReady = true
2448
+ return
2449
+ }
2450
+
2451
+ const firstPageIndex = this.startPage - 1
2452
+ const firstPageUrl = this.pages[firstPageIndex]
2453
+
2454
+ if (!firstPageUrl) {
2455
+ this.contentReady = true
2456
+ return
2457
+ }
2458
+
2459
+ try {
2460
+ await new Promise((resolve, reject) => {
2461
+ const img = new Image()
2462
+ img.onload = () => resolve()
2463
+ img.onerror = () => resolve() // 即使失败也继续
2464
+ img.src = firstPageUrl
2465
+
2466
+ // 超时保护
2467
+ setTimeout(() => resolve(), 3000)
2468
+ })
2469
+ } catch (error) {
2470
+ console.warn('首页图片预加载失败:', error)
2471
+ } finally {
2472
+ this.contentReady = true
2473
+ }
2474
+ },
2475
+
2476
+ /**
2477
+ * 监听窗口尺寸变化
2478
+ */
2479
+ handleResize() {
2480
+ const wasMobile = this.isMobile
2481
+ this.detectMobile()
2482
+
2483
+ // 如果设备类型发生变化,重新初始化flipbook
2484
+ if (wasMobile !== this.isMobile) {
2485
+ console.log('设备类型变化,重新初始化')
2486
+ this.$nextTick(() => {
2487
+ if (this.$refs.flipbook) {
2488
+ // 重置到第一页
2489
+ this.currentPage = 1
2490
+ this.startPage = 1
2491
+ }
2492
+ })
2493
+ }
2494
+ },
2495
+ flipLeft() {
2496
+ console.log('尝试向左翻页,当前页:', this.currentPage)
2497
+ if (this.flipMode === 'flip') {
2498
+ // 仿真翻页模式
2499
+ if (this.$refs.flipbook && this.currentPage > 1) {
2500
+ try {
2501
+ this.$refs.flipbook.flipLeft()
2502
+ console.log('向左翻页命令已发送')
2503
+ } catch (error) {
2504
+ console.error('向左翻页失败:', error)
2505
+ }
2506
+ } else {
2507
+ console.log('无法向左翻页 - 已在第一页或组件未就绪')
2508
+ }
2509
+ } else {
2510
+ // 其他模式直接切换页码
2511
+ if (this.currentPage > 1) {
2512
+ this.currentPage--
2513
+ this.onFlipLeftEnd(this.currentPage)
2514
+ }
2515
+ }
2516
+ },
2517
+ flipRight() {
2518
+ console.log('尝试向右翻页,当前页:', this.currentPage)
2519
+ if (this.flipMode === 'flip') {
2520
+ // 仿真翻页模式
2521
+ if (this.$refs.flipbook && this.currentPage < this.totalPages) {
2522
+ try {
2523
+ this.$refs.flipbook.flipRight()
2524
+ console.log('向右翻页命令已发送')
2525
+ } catch (error) {
2526
+ console.error('向右翻页失败:', error)
2527
+ }
2528
+ } else {
2529
+ console.log('无法向右翻页 - 已在最后一页或组件未就绪')
2530
+ }
2531
+ } else {
2532
+ // 其他模式直接切换页码
2533
+ if (this.currentPage < this.totalPages) {
2534
+ this.currentPage++
2535
+ this.onFlipRightEnd(this.currentPage)
2536
+ }
2537
+ }
2538
+ },
2539
+ onFlipLeftEnd(page) {
2540
+ console.log('向左翻页完成,新页面:', page)
2541
+ this.currentPage = page
2542
+ // 触发页码变化事件
2543
+ this.$emit('page-change', page)
2544
+ // 记录阅读进度
2545
+ this.recordReadingProgress(page)
2546
+ },
2547
+ onFlipRightEnd(page) {
2548
+ console.log('向右翻页完成,新页面:', page)
2549
+ this.currentPage = page
2550
+ // 触发页码变化事件
2551
+ this.$emit('page-change', page)
2552
+ // 记录阅读进度
2553
+ this.recordReadingProgress(page)
2554
+ },
2555
+
2556
+ /**
2557
+ * 容器触摸开始事件
2558
+ */
2559
+ onContainerTouchStart(e) {
2560
+ this.touchStartTime = Date.now()
2561
+ this.initialTouches = Array.from(e.touches)
2562
+
2563
+ if (e.touches.length === 2) {
2564
+ // 双指缩放
2565
+ this.isZooming = true
2566
+ this.lastTouchDistance = this.getTouchDistance(e.touches[0], e.touches[1])
2567
+ this.lastTouchCenter = this.getTouchCenter(e.touches[0], e.touches[1])
2568
+ e.preventDefault()
2569
+ } else if (e.touches.length === 1 && this.zoomScale > 1) {
2570
+ // 单指拖拽(仅在放大状态下)
2571
+ this.isPanning = true
2572
+ this.lastTouchCenter = { x: e.touches[0].clientX, y: e.touches[0].clientY }
2573
+ }
2574
+ },
2575
+
2576
+ /**
2577
+ * 容器触摸移动事件
2578
+ */
2579
+ onContainerTouchMove(e) {
2580
+ if (this.isZooming && e.touches.length === 2) {
2581
+ // 双指缩放
2582
+ const currentDistance = this.getTouchDistance(e.touches[0], e.touches[1])
2583
+ const currentCenter = this.getTouchCenter(e.touches[0], e.touches[1])
2584
+
2585
+ // 计算缩放比例
2586
+ const scaleChange = currentDistance / this.lastTouchDistance
2587
+ let newScale = this.zoomScale * scaleChange
2588
+
2589
+ // 限制缩放范围
2590
+ newScale = Math.max(0.5, Math.min(3, newScale))
2591
+
2592
+ // 计算缩放中心点的偏移
2593
+ const deltaX = currentCenter.x - this.lastTouchCenter.x
2594
+ const deltaY = currentCenter.y - this.lastTouchCenter.y
2595
+
2596
+ this.zoomScale = newScale
2597
+ this.translateX += deltaX
2598
+ this.translateY += deltaY
2599
+
2600
+ this.lastTouchDistance = currentDistance
2601
+ this.lastTouchCenter = currentCenter
2602
+
2603
+ e.preventDefault()
2604
+ } else if (this.isPanning && e.touches.length === 1 && this.zoomScale > 1) {
2605
+ // 单指拖拽
2606
+ const deltaX = e.touches[0].clientX - this.lastTouchCenter.x
2607
+ const deltaY = e.touches[0].clientY - this.lastTouchCenter.y
2608
+
2609
+ this.translateX += deltaX
2610
+ this.translateY += deltaY
2611
+
2612
+ this.lastTouchCenter = { x: e.touches[0].clientX, y: e.touches[0].clientY }
2613
+
2614
+ e.preventDefault()
2615
+ }
2616
+ },
2617
+
2618
+ /**
2619
+ * 容器触摸结束事件
2620
+ */
2621
+ onContainerTouchEnd(e) {
2622
+ const touchDuration = Date.now() - this.touchStartTime
2623
+ const wasZooming = this.isZooming
2624
+ const wasPanning = this.isPanning
2625
+
2626
+ // 先重置状态
2627
+ this.isZooming = false
2628
+ this.isPanning = false
2629
+
2630
+ // 双击重置缩放 - 只在单指快速点击时检测
2631
+ if (e.changedTouches.length === 1 && touchDuration < 300 && !wasZooming && !wasPanning) {
2632
+ const now = Date.now()
2633
+ if (this.lastTapTime && now - this.lastTapTime < 400) {
2634
+ // 检测到双击
2635
+ this.resetZoom()
2636
+ console.log('移动端双击重置显示比例')
2637
+ this.lastTapTime = 0 // 重置,避免三击触发
2638
+ } else {
2639
+ this.lastTapTime = now
2640
+ }
2641
+ }
2642
+
2643
+ // 边界检查和回弹
2644
+ this.constrainPosition()
2645
+ },
2646
+
2647
+ /**
2648
+ * 获取两点间距离
2649
+ */
2650
+ getTouchDistance(touch1, touch2) {
2651
+ const dx = touch1.clientX - touch2.clientX
2652
+ const dy = touch1.clientY - touch2.clientY
2653
+ return Math.sqrt(dx * dx + dy * dy)
2654
+ },
2655
+
2656
+ /**
2657
+ * 获取两点中心
2658
+ */
2659
+ getTouchCenter(touch1, touch2) {
2660
+ return {
2661
+ x: (touch1.clientX + touch2.clientX) / 2,
2662
+ y: (touch1.clientY + touch2.clientY) / 2
2663
+ }
2664
+ },
2665
+
2666
+ /**
2667
+ * 重置缩放
2668
+ */
2669
+ resetZoom() {
2670
+ this.zoomScale = 1
2671
+ this.translateX = 0
2672
+ this.translateY = 0
2673
+ },
2674
+
2675
+ /**
2676
+ * PC端双击事件处理
2677
+ */
2678
+ onContainerDoubleClick(e) {
2679
+ // 阻止事件冒泡和默认行为,避免触发翻页
2680
+ e.preventDefault()
2681
+ e.stopPropagation()
2682
+
2683
+ // 重置缩放比例
2684
+ this.resetZoom()
2685
+ console.log('容器双击重置显示比例,当前缩放:', this.zoomScale)
2686
+ },
2687
+
2688
+ /**
2689
+ * Flipbook区域双击事件处理
2690
+ */
2691
+ onFlipbookDoubleClick(e) {
2692
+ // 阻止事件冒泡和默认行为,避免触发翻页
2693
+ e.preventDefault()
2694
+ e.stopPropagation()
2695
+
2696
+ // 重置缩放比例
2697
+ this.resetZoom()
2698
+ console.log('Flipbook双击重置显示比例,当前缩放:', this.zoomScale)
2699
+ },
2700
+
2701
+ /**
2702
+ * Flipbook区域触摸开始事件
2703
+ */
2704
+ onFlipbookTouchStart(e) {
2705
+ this.flipbookTouchStartTime = Date.now()
2706
+ },
2707
+
2708
+ /**
2709
+ * Flipbook区域触摸结束事件(移动端双击检测)
2710
+ */
2711
+ onFlipbookTouchEnd(e) {
2712
+ const touchDuration = Date.now() - this.flipbookTouchStartTime
2713
+
2714
+ // 双击重置缩放 - 只在单指快速点击时检测
2715
+ if (e.changedTouches.length === 1 && touchDuration < 300) {
2716
+ const now = Date.now()
2717
+ if (this.flipbookLastTapTime && now - this.flipbookLastTapTime < 400) {
2718
+ // 检测到双击
2719
+ e.preventDefault()
2720
+ e.stopPropagation()
2721
+ this.resetZoom()
2722
+ console.log('Flipbook区域移动端双击重置显示比例')
2723
+ this.flipbookLastTapTime = 0 // 重置,避免三击触发
2724
+ } else {
2725
+ this.flipbookLastTapTime = now
2726
+ }
2727
+ }
2728
+ },
2729
+
2730
+ /**
2731
+ * 约束位置在边界内
2732
+ */
2733
+ constrainPosition() {
2734
+ if (this.zoomScale <= 1) {
2735
+ this.translateX = 0
2736
+ this.translateY = 0
2737
+ return
2738
+ }
2739
+
2740
+ const maxTranslate = (this.zoomScale - 1) * 200
2741
+ this.translateX = Math.max(-maxTranslate, Math.min(maxTranslate, this.translateX))
2742
+ this.translateY = Math.max(-maxTranslate, Math.min(maxTranslate, this.translateY))
2743
+ },
2744
+
2745
+
2746
+ /**
2747
+ * 打开目录抽屉
2748
+ */
2749
+ openCatalogue() {
2750
+ console.log('点击目录按钮', {
2751
+ dragging: this.catalogueButtonDragging,
2752
+ showDrawer: this.showCatalogueDrawer
2753
+ })
2754
+
2755
+ // 只有在不是拖拽状态下才打开目录
2756
+ if (!this.catalogueButtonDragging) {
2757
+ this.showCatalogueDrawer = true
2758
+ console.log('目录抽屉已打开')
2759
+ } else {
2760
+ console.log('拖拽状态中,不打开目录')
2761
+ }
2762
+ },
2763
+
2764
+ /**
2765
+ * 目录按钮拖拽开始
2766
+ */
2767
+ onCatalogueMouseDown(e) {
2768
+ // 不立即设置为拖拽状态,等待移动再判断
2769
+ this.catalogueButtonDragging = false
2770
+
2771
+ const rect = e.target.closest('.catalogue-button').getBoundingClientRect()
2772
+ this.dragStartPosition = {
2773
+ x: e.clientX,
2774
+ y: e.clientY
2775
+ }
2776
+ this.dragOffset = {
2777
+ x: e.clientX - rect.left,
2778
+ y: e.clientY - rect.top
2779
+ }
2780
+
2781
+ document.addEventListener('mousemove', this.onCatalogueMouseMove)
2782
+ document.addEventListener('mouseup', this.onCatalogueMouseUp)
2783
+ },
2784
+
2785
+ /**
2786
+ * 目录按钮拖拽移动
2787
+ */
2788
+ onCatalogueMouseMove(e) {
2789
+ // 检查是否开始拖拽
2790
+ const dragDistance = Math.sqrt(
2791
+ Math.pow(e.clientX - this.dragStartPosition.x, 2) +
2792
+ Math.pow(e.clientY - this.dragStartPosition.y, 2)
2793
+ )
2794
+
2795
+ // 只有移动距离超过5px才认为是拖拽
2796
+ if (dragDistance > 5) {
2797
+ this.catalogueButtonDragging = true
2798
+ }
2799
+
2800
+ if (!this.catalogueButtonDragging) return
2801
+
2802
+ e.preventDefault()
2803
+
2804
+ const newX = e.clientX - this.dragOffset.x
2805
+ const newY = e.clientY - this.dragOffset.y
2806
+
2807
+ // 限制在视窗范围内
2808
+ const maxX = window.innerWidth - 120 // 按钮宽度约120px
2809
+ const maxY = window.innerHeight - 50 // 按钮高度约50px
2810
+
2811
+ this.catalogueButtonPosition = {
2812
+ x: Math.max(0, Math.min(maxX, newX)),
2813
+ y: Math.max(0, Math.min(maxY, newY))
2814
+ }
2815
+ },
2816
+
2817
+ /**
2818
+ * 目录按钮拖拽结束
2819
+ */
2820
+ onCatalogueMouseUp(e) {
2821
+ // 立即重置拖拽状态
2822
+ this.catalogueButtonDragging = false
2823
+
2824
+ document.removeEventListener('mousemove', this.onCatalogueMouseMove)
2825
+ document.removeEventListener('mouseup', this.onCatalogueMouseUp)
2826
+ },
2827
+
2828
+ /**
2829
+ * 目录按钮触摸开始(移动端)
2830
+ */
2831
+ onCatalogueTouchStart(e) {
2832
+ // 不立即设置为拖拽状态
2833
+ this.catalogueButtonDragging = false
2834
+
2835
+ const touch = e.touches[0]
2836
+ const rect = e.target.closest('.catalogue-button').getBoundingClientRect()
2837
+
2838
+ this.dragStartPosition = {
2839
+ x: touch.clientX,
2840
+ y: touch.clientY
2841
+ }
2842
+ this.dragOffset = {
2843
+ x: touch.clientX - rect.left,
2844
+ y: touch.clientY - rect.top
2845
+ }
2846
+ },
2847
+
2848
+ /**
2849
+ * 目录按钮触摸移动(移动端)
2850
+ */
2851
+ onCatalogueTouchMove(e) {
2852
+ const touch = e.touches[0]
2853
+
2854
+ // 检查是否开始拖拽
2855
+ const dragDistance = Math.sqrt(
2856
+ Math.pow(touch.clientX - this.dragStartPosition.x, 2) +
2857
+ Math.pow(touch.clientY - this.dragStartPosition.y, 2)
2858
+ )
2859
+
2860
+ // 只有移动距离超过5px才认为是拖拽
2861
+ if (dragDistance > 5) {
2862
+ this.catalogueButtonDragging = true
2863
+ }
2864
+
2865
+ if (!this.catalogueButtonDragging) return
2866
+
2867
+ e.preventDefault()
2868
+
2869
+ const newX = touch.clientX - this.dragOffset.x
2870
+ const newY = touch.clientY - this.dragOffset.y
2871
+
2872
+ // 限制在视窗范围内,考虑安全区域
2873
+ const maxX = window.innerWidth - 120
2874
+ const maxY = window.innerHeight - 80
2875
+
2876
+ this.catalogueButtonPosition = {
2877
+ x: Math.max(15, Math.min(maxX, newX)),
2878
+ y: Math.max(15, Math.min(maxY, newY))
2879
+ }
2880
+ },
2881
+
2882
+ /**
2883
+ * 目录按钮触摸结束(移动端)
2884
+ */
2885
+ onCatalogueTouchEnd(e) {
2886
+ // 立即重置拖拽状态
2887
+ this.catalogueButtonDragging = false
2888
+ },
2889
+
2890
+ /**
2891
+ * 切换翻页模式菜单显示
2892
+ */
2893
+ toggleFlipModeMenu() {
2894
+ this.showFlipModeMenu = !this.showFlipModeMenu
2895
+ },
2896
+
2897
+ /**
2898
+ * 选择翻页模式
2899
+ * @param {string} mode - 翻页模式
2900
+ */
2901
+ selectFlipMode(mode) {
2902
+ const oldMode = this.flipMode
2903
+ this.flipMode = mode
2904
+ this.showFlipModeMenu = false
2905
+
2906
+ // 保存翻页模式到本地存储
2907
+ localStorage.setItem('book-viewer-flip-mode', mode)
2908
+
2909
+ console.log('切换翻页模式:', { from: oldMode, to: mode })
2910
+
2911
+ // 如果切换到滚动模式,需要滚动到当前页
2912
+ if (mode === 'scroll') {
2913
+ this.$nextTick(() => {
2914
+ this.scrollToCurrentPage()
2915
+ })
2916
+ }
2917
+ },
2918
+
2919
+ /**
2920
+ * 滑动模式触摸开始
2921
+ */
2922
+ onSlideViewerTouchStart(e) {
2923
+ if (e.touches.length === 1) {
2924
+ this.slideStartX = e.touches[0].clientX
2925
+ this.slideCurrentX = e.touches[0].clientX
2926
+ this.slideIsDragging = true
2927
+ }
2928
+ },
2929
+
2930
+ /**
2931
+ * 滑动模式触摸移动
2932
+ */
2933
+ onSlideViewerTouchMove(e) {
2934
+ if (this.slideIsDragging && e.touches.length === 1) {
2935
+ this.slideCurrentX = e.touches[0].clientX
2936
+ e.preventDefault()
2937
+ }
2938
+ },
2939
+
2940
+ /**
2941
+ * 滑动模式触摸结束
2942
+ */
2943
+ onSlideViewerTouchEnd(e) {
2944
+ if (this.slideIsDragging) {
2945
+ const deltaX = this.slideCurrentX - this.slideStartX
2946
+ const threshold = 50 // 滑动阈值
2947
+
2948
+ if (deltaX > threshold && this.currentPage > 1) {
2949
+ // 向右滑动,上一页
2950
+ this.currentPage--
2951
+ this.recordReadingProgress(this.currentPage)
2952
+ } else if (deltaX < -threshold && this.currentPage < this.totalPages) {
2953
+ // 向左滑动,下一页
2954
+ this.currentPage++
2955
+ this.recordReadingProgress(this.currentPage)
2956
+ }
2957
+
2958
+ this.slideIsDragging = false
2959
+ }
2960
+ },
2961
+
2962
+ /**
2963
+ * 滚动模式滚动事件
2964
+ */
2965
+ onScrollViewerScroll(e) {
2966
+ const container = this.$refs.scrollViewer
2967
+ if (!container) return
2968
+
2969
+ const scrollTop = container.scrollTop
2970
+ const containerHeight = container.clientHeight
2971
+
2972
+ // 计算当前页码
2973
+ for (let i = 0; i < this.pages.length; i++) {
2974
+ const pageRef = this.$refs['scrollPage' + i]
2975
+ if (pageRef && pageRef[0]) {
2976
+ const pageTop = pageRef[0].offsetTop
2977
+ const pageBottom = pageTop + pageRef[0].offsetHeight
2978
+
2979
+ if (scrollTop >= pageTop - containerHeight / 2 && scrollTop < pageBottom - containerHeight / 2) {
2980
+ if (this.currentPage !== i + 1) {
2981
+ this.currentPage = i + 1
2982
+ this.recordReadingProgress(this.currentPage)
2983
+ }
2984
+ break
2985
+ }
2986
+ }
2987
+ }
2988
+ },
2989
+
2990
+ /**
2991
+ * 滚动到当前页
2992
+ */
2993
+ scrollToCurrentPage() {
2994
+ if (this.flipMode !== 'scroll') return
2995
+
2996
+ const pageRef = this.$refs['scrollPage' + (this.currentPage - 1)]
2997
+ if (pageRef && pageRef[0]) {
2998
+ pageRef[0].scrollIntoView({ behavior: 'smooth', block: 'start' })
2999
+ }
3000
+ },
3001
+
3002
+ /**
3003
+ * 关闭翻页模式菜单(点击外部)
3004
+ */
3005
+ closeFlipModeMenu(e) {
3006
+ if (!e.target.closest('.flip-mode-selector')) {
3007
+ this.showFlipModeMenu = false
3008
+ }
3009
+ },
3010
+
3011
+ /**
3012
+ * 获取卡片样式
3013
+ * @param {string} position - 卡片位置:prev, current, next
3014
+ */
3015
+ getCardStyle(position) {
3016
+ switch (position) {
3017
+ case 'prev':
3018
+ return {
3019
+ transform: 'translateX(-70%) scale(0.85) rotateY(15deg)',
3020
+ zIndex: 1,
3021
+ opacity: 0.6,
3022
+ filter: 'brightness(0.8)'
3023
+ }
3024
+ case 'current':
3025
+ return {
3026
+ transform: 'translateX(0) scale(1) rotateY(0deg)',
3027
+ zIndex: 3,
3028
+ opacity: 1,
3029
+ filter: 'brightness(1)'
3030
+ }
3031
+ case 'next':
3032
+ return {
3033
+ transform: 'translateX(70%) scale(0.85) rotateY(-15deg)',
3034
+ zIndex: 1,
3035
+ opacity: 0.6,
3036
+ filter: 'brightness(0.8)'
3037
+ }
3038
+ default:
3039
+ return {}
3040
+ }
3041
+ },
3042
+
3043
+ /**
3044
+ * 目录项点击事件
3045
+ * @param {Object} item - 点击的目录项
3046
+ */
3047
+ onCatalogueClick(item) {
3048
+ console.log('目录项被点击:', item)
3049
+ this.$emit('catalogue-click', item)
3050
+ },
3051
+
3052
+ /**
3053
+ * 获取目录数据事件
3054
+ * @param {String} bookId - 书籍ID
3055
+ */
3056
+ onFetchCatalogue(bookId) {
3057
+ this.$emit('fetch-catalogue', bookId)
3058
+ },
3059
+
3060
+ /**
3061
+ * 页面跳转事件
3062
+ * @param {number} pageNumber - 目标页码
3063
+ */
3064
+ onFocus() {
3065
+ // 使用flipbook的方法跳转到指定页面
3066
+ if (this.flipMode === 'flip') {
3067
+ this.flag = false
3068
+ setTimeout(() => {
3069
+ this.flag = true
3070
+ }, 500)
3071
+ } else if (this.flipMode === 'scroll') {
3072
+ this.scrollToCurrentPage()
3073
+ }
3074
+ },
3075
+ onPageJump(pageNumber) {
3076
+ console.log('跳转到页面:', pageNumber)
3077
+
3078
+ // 关闭目录抽屉
3079
+ this.showCatalogueDrawer = false
3080
+
3081
+ // 跳转到指定页面
3082
+ if (pageNumber && pageNumber >= 1 && pageNumber <= this.totalPages) {
3083
+ this.currentPage = pageNumber
3084
+ this.startPage = pageNumber
3085
+
3086
+ // 记录阅读进度
3087
+ this.recordReadingProgress(pageNumber)
3088
+
3089
+ // 使用flipbook的方法跳转到指定页面
3090
+ if (this.flipMode === 'flip') {
3091
+ this.flag = false
3092
+ setTimeout(() => {
3093
+ this.flag = true
3094
+ this.$nextTick(() => {
3095
+ this.$refs.flipbook.goToPage(pageNumber)
3096
+ })
3097
+ }, 500)
3098
+ } else if (this.flipMode === 'scroll') {
3099
+ this.scrollToCurrentPage()
3100
+ }
3101
+ } else {
3102
+ console.warn('无效的页码:', pageNumber)
3103
+ }
3104
+ },
3105
+
3106
+ /**
3107
+ * 检查URL参数并跳转到指定页码
3108
+ */
3109
+ checkUrlPageParameter() {
3110
+ // 从URL查询参数中获取页码
3111
+ const pageParam = this.$route.query.page
3112
+
3113
+ if (pageParam) {
3114
+ const targetPage = parseInt(pageParam, 10)
3115
+
3116
+ console.log('检测到URL页码参数:', {
3117
+ pageParam,
3118
+ targetPage,
3119
+ totalPages: this.totalPages
3120
+ })
3121
+
3122
+ // 验证页码是否有效
3123
+ if (!isNaN(targetPage) && targetPage >= 1 && targetPage <= this.totalPages) {
3124
+ console.log('准备跳转到页码:', targetPage)
3125
+
3126
+ // 使用nextTick确保DOM已更新
3127
+ this.$nextTick(() => {
3128
+ this.jumpToPage(targetPage)
3129
+ })
3130
+ } else {
3131
+ console.warn('无效的页码参数:', {
3132
+ pageParam,
3133
+ targetPage,
3134
+ totalPages: this.totalPages,
3135
+ isValid: !isNaN(targetPage) && targetPage >= 1 && targetPage <= this.totalPages
3136
+ })
3137
+ }
3138
+ } else {
3139
+ console.log('URL中未检测到页码参数')
3140
+ }
3141
+ },
3142
+
3143
+ /**
3144
+ * 跳转到指定页码
3145
+ * @param {number} pageNumber - 目标页码
3146
+ */
3147
+ jumpToPage(pageNumber) {
3148
+ if (!pageNumber || pageNumber < 1 || pageNumber > this.totalPages) {
3149
+ console.warn('无效的页码:', pageNumber)
3150
+ return
3151
+ }
3152
+
3153
+ console.log('跳转到页面:', pageNumber)
3154
+
3155
+ // 更新当前页码和起始页码
3156
+ this.currentPage = pageNumber
3157
+ this.startPage = pageNumber
3158
+
3159
+ // 记录阅读进度
3160
+ this.recordReadingProgress(pageNumber)
3161
+
3162
+ // 使用flipbook的方法跳转到指定页面
3163
+ if (this.flipMode === 'flip') {
3164
+ if (this.$refs.flipbook && this.$refs.flipbook.goToPage) {
3165
+ try {
3166
+ this.$refs.flipbook.goToPage(pageNumber)
3167
+ console.log('页面跳转成功:', pageNumber)
3168
+ } catch (error) {
3169
+ console.error('页面跳转失败:', error)
3170
+ }
3171
+ } else {
3172
+ console.warn('Flipbook组件未就绪,无法跳转页面')
3173
+ }
3174
+ } else if (this.flipMode === 'scroll') {
3175
+ this.scrollToCurrentPage()
3176
+ }
3177
+ // slide 和 fade 模式直接通过 currentPage 变化来切换
3178
+ },
3179
+
3180
+ /**
3181
+ * 记录阅读进度
3182
+ * @param {number} pageNumber - 当前页码
3183
+ */
3184
+ async recordReadingProgress(pageNumber) {
3185
+ if (!this.bookId || !pageNumber) {
3186
+ console.warn('缺少书籍ID或页码,无法记录阅读进度')
3187
+ return
3188
+ }
3189
+
3190
+ try {
3191
+ console.log('记录阅读进度:', {
3192
+ bookId: this.bookId,
3193
+ pageNumber: pageNumber
3194
+ })
3195
+
3196
+ // 注释:原来调用API记录进度,现在改为触发事件让父组件处理
3197
+ // await booksApi.recordReadProgress(this.bookId, pageNumber)
3198
+ this.$emit('record-progress', { bookId: this.bookId, pageNumber })
3199
+
3200
+ console.log('阅读进度记录成功')
3201
+
3202
+ } catch (error) {
3203
+ console.error('记录阅读进度失败:', error)
3204
+ // 阅读记录失败不影响用户体验,只记录日志
3205
+ }
3206
+ },
3207
+
3208
+ /**
3209
+ * 显示控件
3210
+ */
3211
+ showControlsTemporarily() {
3212
+ this.showControls = true
3213
+
3214
+ // 清除之前的定时器
3215
+ if (this.hideControlsTimer) {
3216
+ clearTimeout(this.hideControlsTimer)
3217
+ }
3218
+
3219
+ // 3秒后自动隐藏
3220
+ this.hideControlsTimer = setTimeout(() => {
3221
+ this.showControls = false
3222
+ }, 3000)
3223
+ },
3224
+
3225
+ /**
3226
+ * 内容区域点击事件
3227
+ */
3228
+ onContentClick() {
3229
+ this.showControlsTemporarily()
3230
+ },
3231
+
3232
+ /**
3233
+ * 处理页码输入
3234
+ */
3235
+ handlePageInput(e) {
3236
+ const value = e.target.value
3237
+ // 只允许输入数字
3238
+ const numValue = value.replace(/[^\d]/g, '')
3239
+ // 限制不超过总页数
3240
+ if (numValue && parseInt(numValue) > this.totalPages) {
3241
+ this.jumpPageInput = this.totalPages.toString()
3242
+ } else {
3243
+ this.jumpPageInput = numValue
3244
+ }
3245
+ },
3246
+
3247
+ /**
3248
+ * 执行页码跳转
3249
+ */
3250
+ handleJumpToPage() {
3251
+ const pageNum = parseInt(this.jumpPageInput)
3252
+ if (pageNum && pageNum >= 1 && pageNum <= this.totalPages) {
3253
+ // 重置缩放和位移,避免内容区域缩小
3254
+ this.resetZoom()
3255
+ this.jumpToPage(pageNum)
3256
+ this.jumpPageInput = ''
3257
+ }
3258
+ }
3259
+ },
3260
+ watch: {
3261
+ async pages(newPages) {
3262
+ if (newPages && newPages.length > 0 && this.isMobile) {
3263
+ this.contentReady = false
3264
+ await this.$nextTick()
3265
+ await this.preloadFirstPage()
3266
+ } else if (newPages && newPages.length > 0) {
3267
+ this.contentReady = true
3268
+ }
3269
+ }
3270
+ },
3271
+ async mounted() {
3272
+ console.log('组件已挂载,总页数:', this.totalPages)
3273
+
3274
+ // 检测设备类型
3275
+ this.detectMobile()
3276
+
3277
+ // 检查URL参数中的翻页模式
3278
+ const urlFlipMode = this.$route.query.mode || this.$route.query.flipMode
3279
+ if (urlFlipMode && this.flipModes.some(m => m.value === urlFlipMode)) {
3280
+ // URL参数指定的翻页模式优先级最高,并隐藏切换按钮
3281
+ this.flipMode = urlFlipMode
3282
+ this.flipModeFromUrl = true
3283
+ console.log('从URL参数读取翻页模式:', urlFlipMode)
3284
+ } else {
3285
+ // 否则从本地存储恢复
3286
+ const savedFlipMode = localStorage.getItem('book-viewer-flip-mode')
3287
+ if (savedFlipMode && this.flipModes.some(m => m.value === savedFlipMode)) {
3288
+ this.flipMode = savedFlipMode
3289
+ }
3290
+ }
3291
+
3292
+ // 预加载首页图片(移动端优化)
3293
+ if (this.isMobile && this.pages && this.pages.length > 0) {
3294
+ await this.$nextTick()
3295
+ await this.preloadFirstPage()
3296
+ } else if (this.pages && this.pages.length > 0) {
3297
+ this.contentReady = true
3298
+ }
3299
+
3300
+ // 监听窗口尺寸变化
3301
+ window.addEventListener('resize', this.handleResize)
3302
+
3303
+ // 监听点击事件,用于关闭翻页模式菜单
3304
+ document.addEventListener('click', this.closeFlipModeMenu)
3305
+ },
3306
+
3307
+ beforeDestroy() {
3308
+ // 清理事件监听
3309
+ window.removeEventListener('resize', this.handleResize)
3310
+ // 清理拖拽事件监听
3311
+ document.removeEventListener('mousemove', this.onCatalogueMouseMove)
3312
+ document.removeEventListener('mouseup', this.onCatalogueMouseUp)
3313
+ // 清理翻页模式菜单事件监听
3314
+ document.removeEventListener('click', this.closeFlipModeMenu)
3315
+ // 清理控件自动隐藏定时器
3316
+ if (this.hideControlsTimer) {
3317
+ clearTimeout(this.hideControlsTimer)
3318
+ }
3319
+ }
3320
+ });
3321
+
3322
+ ;// ./src/components/BookReader.vue?vue&type=script&lang=js
3323
+ /* harmony default export */ var components_BookReadervue_type_script_lang_js = (BookReadervue_type_script_lang_js);
3324
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-52.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-52.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-52.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/BookReader.vue?vue&type=style&index=0&id=eaca7004&prod&scoped=true&lang=css
3325
+ // extracted by mini-css-extract-plugin
3326
+
3327
+ ;// ./src/components/BookReader.vue?vue&type=style&index=0&id=eaca7004&prod&scoped=true&lang=css
3328
+
3329
+ ;// ./src/components/BookReader.vue
3330
+
3331
+
3332
+
3333
+ ;
3334
+
3335
+
3336
+ /* normalize component */
3337
+
3338
+ var BookReader_component = componentNormalizer_normalizeComponent(
3339
+ components_BookReadervue_type_script_lang_js,
3340
+ render,
3341
+ staticRenderFns,
3342
+ false,
3343
+ null,
3344
+ "eaca7004",
3345
+ null
3346
+
3347
+ )
3348
+
3349
+ /* harmony default export */ var BookReader = (BookReader_component.exports);
3350
+ ;// ./src/index.js
3351
+
3352
+
3353
+
3354
+ const components = {
3355
+ BookReader: BookReader,
3356
+ BookCatalogueDrawer: BookCatalogueDrawer
3357
+ }
3358
+
3359
+ const install = function(Vue) {
3360
+ if (install.installed) return
3361
+ install.installed = true
3362
+ Object.keys(components).forEach(key => {
3363
+ Vue.component(key, components[key])
3364
+ })
3365
+ }
3366
+
3367
+ if (typeof window !== 'undefined' && window.Vue) {
3368
+ install(window.Vue)
3369
+ }
3370
+
3371
+ /* harmony default export */ var src_0 = ({
3372
+ install,
3373
+ BookReader: BookReader,
3374
+ BookCatalogueDrawer: BookCatalogueDrawer
3375
+ });
3376
+
3377
+
3378
+
3379
+ ;// ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js
3380
+
3381
+
3382
+ /* harmony default export */ var entry_lib = (src_0);
3383
+
3384
+
3385
+ /******/ return __webpack_exports__;
3386
+ /******/ })()
3387
+ ;
3388
+ });
3389
+ //# sourceMappingURL=vue-book-reader.umd.js.map