index.js 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719
  1. import { getDocument, GlobalWorkerOptions, InvalidPDFException, MissingPDFException, UnexpectedResponseException, getPdfFilenameFromUrl } from 'pdfjs-dist/legacy/build/pdf'
  2. import CryptoJS from 'crypto-js'
  3. import printJS from 'print-js'
  4. import { saveAs } from 'file-saver'
  5. import { PDFLinkService } from "./pdf_link_service"
  6. import { PasswordPrompt } from "./password_prompt.js";
  7. import { PDFViewer } from './pdf_viewer'
  8. import { PDFThumbnailViewer } from './pdf_thumbnail_viewer'
  9. import { PDFRenderingQueue } from "./pdf_rendering_queue";
  10. import { PDFSidebar } from "./pdf_sidebar.js";
  11. import { GenericExternalServices } from "./genericcom.js";
  12. import { PDFCursorTools } from "./pdf_cursor_tools.js";
  13. import { EventBus, isValidRotation, isValidScrollMode, shadow, isValidSpreadMode, toDateObject, findIndex, scrollIntoView, DEFAULT_SCALE_VALUE, SidebarView, parseAnnotationFromXml, PromiseExt, parseAdobePDFTimestamp, round } from './ui_utils'
  14. import { AnnotationTypeString } from "../constants";
  15. import { PDFPresentationMode } from "./pdf_presentation_mode.js";
  16. import annotationStore from "./annotation_store"
  17. import { InkSign } from "./ink_sign"
  18. import MessageHandler from "./message_handler"
  19. import JSZip from 'jszip'
  20. import Outline from './Outline'
  21. GlobalWorkerOptions.workerSrc = './lib/pdf.worker.min.js'
  22. const CMAP_URL = './cmaps/'
  23. class ComPDFKitViewer {
  24. #pwd = ''
  25. #oldPwd = ''
  26. #textSearch = null
  27. #activeSearchIndex = 0
  28. #fonFile = null
  29. constructor(options) {
  30. this.config = options
  31. this.viewerContainer = null
  32. this.pdfLoadingTask = null
  33. this.printService = null
  34. this.pdfSidebar = null
  35. this.pdfOutlineViewer = null
  36. this.outlines = []
  37. this.pdfLayerViewer = null
  38. this.pdfDocument = null
  39. this.downloadComplete = false
  40. this.isInitialViewSet = false
  41. this.pdfLinkService = null
  42. this.externalServices = GenericExternalServices
  43. this.percent = 0
  44. this.pageChangedCallback = null
  45. this.scaleChangedCallback = null
  46. this.annotationsNumChangedCallback = null
  47. this.distanceChangedCallback = null
  48. this._license = ''
  49. this._token = null
  50. this._pdfId = null
  51. this.annotations = null
  52. this.annotationHistory = []
  53. this._annotationMode = 0
  54. this._boundEvents = Object.create(null)
  55. this._title = document.title
  56. this.activeTool = ''
  57. this.color = 'color'
  58. this.pagesPtr = []
  59. this.saveAction = null
  60. this.optionUrl = {
  61. baseUrl: 'https://test-compdf.kdan.cn',
  62. // baseUrl: 'https://wms.compdf.com',
  63. verifyUrl: '/api/license/verify',
  64. webviewBaseUrl: 'https://test-pdf-pro.kdan.cn:3032',
  65. // webviewBaseUrl: 'https://web-viewer-backend.compdf.com',
  66. uploadUrl: '/web-viewer/annotate/openPdfToAnnotate',
  67. editUrl: '/web-viewer/annotate/edit',
  68. saveUrl: '/web-viewer/annotate/save',
  69. flattenUrl: '/web-viewer/annotate/saveAndFlatten',
  70. uploadAnnotationsUrl: '/web-viewer/annotate/importAnnotateToPdf',
  71. downloadAnnotation: '/web-viewer/annotate/exportAnnotate',
  72. compareUrl: '/web-viewer/annotate/pdfCompare'
  73. }
  74. this.eventBus = new EventBus();
  75. this.toolMode = ''
  76. this.$t = options.$t
  77. this.fontFileInited = false
  78. this.contentEditAnnotationsManager = {}
  79. }
  80. get pagesCount() {
  81. return this.doc ? this._pagesCount : 0;
  82. }
  83. get annotationsCount() {
  84. return this.pdfViewer.annotationStorage ? this.pdfViewer.annotationStorage.size : 0;
  85. }
  86. get page() {
  87. return this.pdfViewer.currentPageNumber;
  88. }
  89. set page(val) {
  90. this.pdfViewer.currentPageNumber = val;
  91. }
  92. get currentPageNumber() {
  93. return this.pdfViewer.currentPageNumber
  94. }
  95. get scale() {
  96. return this.pdfViewer.currentScale;
  97. }
  98. async init() {
  99. await new Promise((resolve, reject) => {
  100. const worker = new PDFWorker()
  101. this.worker = worker
  102. const messageHandler = worker.messageHandler
  103. this.messageHandler = messageHandler
  104. messageHandler.on('initDoc', ({ doc }) => {
  105. this.doc = doc
  106. resolve(true)
  107. })
  108. })
  109. }
  110. async initConfig(options) {
  111. if (!options.license) return false
  112. this._license = options.license
  113. const data = {
  114. method: 'POST',
  115. headers: {
  116. 'Content-Type': 'application/json'
  117. },
  118. body: JSON.stringify({
  119. license: this._license
  120. })
  121. }
  122. if (options.webviewerServer === 'Server') {
  123. this.webviewerServer = true
  124. }
  125. // this.webviewerServer = true
  126. const verified = await fetch(this.optionUrl.baseUrl + this.optionUrl.verifyUrl, data)
  127. .then((res) => {
  128. return res.json()
  129. })
  130. .then((resp) => {
  131. if (resp.code === 200) {
  132. const verified = this._decrypt(resp.data)
  133. return verified
  134. } else {
  135. alert(resp.message)
  136. return false
  137. }
  138. })
  139. .catch((error) => {
  140. alert('Network Error')
  141. console.log({ error: true, message: error.message })
  142. return false
  143. });
  144. if (verified) {
  145. if (!this.webviewerServer) {
  146. const response = await fetch('./lib/DroidSansFallbackFull.ttf')
  147. const blob = await response.blob()
  148. this.#fonFile = new File([blob], 'DroidSansFallbackFull.ttf', { type: blob.type })
  149. }
  150. await this.init()
  151. }
  152. return verified
  153. }
  154. _decrypt(data) {
  155. const decrypt = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse('T2EKWNOflrd6ICU5'), {
  156. iv: CryptoJS.enc.Utf8.parse('GM3Faw9kX7CBmojt')
  157. })
  158. const decrypted = JSON.parse(decrypt.toString(CryptoJS.enc.Utf8))
  159. const hostname = window.location.hostname
  160. const reg = new RegExp(`^.*${decrypted.domain}$`);
  161. if (reg.test(hostname) || data.app_type === 2) {
  162. this._token = decrypted.token
  163. return true
  164. }
  165. return false
  166. }
  167. initializeViewer({
  168. container,
  169. viewer,
  170. thumbnailView,
  171. annotationView,
  172. findbarView,
  173. toggleButton,
  174. }) {
  175. this._initializeViewerComponents({
  176. container,
  177. viewer,
  178. thumbnailView,
  179. annotationView,
  180. findbarView,
  181. toggleButton,
  182. })
  183. this.initBindEvents()
  184. if (thumbnailView && annotationView) {
  185. this.bindEvents();
  186. this.bindWindowEvents();
  187. }
  188. }
  189. setTool({
  190. tool,
  191. color
  192. }) {
  193. this.activeTool = tool
  194. this.color = color
  195. this.eventBus.dispatch("toolChanged", { tool, color });
  196. }
  197. initAnnotations(annotations, render = false) {
  198. for (let index = 0; index < annotations.length; index++) {
  199. this.handleAnnotations(annotations[index], true)
  200. render && this.pdfViewer.renderAnnotation(annotations[index])
  201. }
  202. this.eventBus.dispatch('annotationChanged', { annotations: this.annotations })
  203. }
  204. async handleAnnotations(annotation, init = false) {
  205. if (!this.annotations) {
  206. this.annotations = {}
  207. }
  208. if (init) {
  209. this.initAddAnnotations(annotation)
  210. } else {
  211. if (Number(annotation.pageIndex) + 1 > this.pagesCount) return
  212. this.pushAnnotations(annotation)
  213. if (!this.webviewerServer || annotation.type === 'stamp') {
  214. const pagePtr = this.pagesPtr[annotation.pageIndex].pagePtr
  215. const annotPtr = await this.messageHandler.sendWithPromise('CreateAnnotation', {
  216. doc: this.doc,
  217. pagePtr,
  218. annotation
  219. })
  220. annotation.pagePtr = pagePtr
  221. annotation.annotPtr = annotPtr
  222. if (!annotation.rect && this.webviewerServer) {
  223. const getRect = await this.messageHandler.sendWithPromise('GetAnnotRect', {
  224. pagePtr: pagePtr,
  225. annotPtr: annotPtr
  226. })
  227. let pageView = this.pdfViewer.getPageView(annotation.pageIndex)
  228. const pageWidth = pageView.viewport.viewBox[2]
  229. const pageHeight = pageView.viewport.viewBox[3]
  230. const imgWidth = getRect.right - getRect.left
  231. const imgHeight = getRect.bottom - getRect.top
  232. const left = (pageWidth - imgWidth) / 2
  233. const top = (pageHeight - imgHeight) / 2
  234. const right = (pageWidth + imgWidth) / 2
  235. const bottom = (pageHeight + imgHeight) / 2
  236. const rect = {
  237. left,
  238. top,
  239. right,
  240. bottom,
  241. }
  242. annotation.rect = rect
  243. }
  244. }
  245. }
  246. }
  247. initAddAnnotations(annotation) {
  248. const pageIndex = annotation.pageIndex
  249. const annotations = this.annotations
  250. if (!annotations[pageIndex]) {
  251. annotations[pageIndex] = []
  252. }
  253. console.log(typeof annotation.index)
  254. if (typeof annotation.index !== 'undefined') {
  255. annotations[pageIndex][annotation.index] = annotation
  256. } else {
  257. annotations[pageIndex].push(annotation)
  258. }
  259. if (!annotationStore.annotationsAll) {
  260. annotationStore.annotationsAll = annotations
  261. }
  262. }
  263. pushAnnotations(annotation) {
  264. const pageIndex = annotation.pageIndex
  265. const annotations = this.annotations
  266. if (!annotations[pageIndex]) {
  267. annotations[pageIndex] = []
  268. this.pdfViewer._pages[pageIndex].annotations = annotations[pageIndex]
  269. }
  270. if (!annotationStore.annotationsAll) {
  271. annotationStore.annotationsAll = annotations
  272. }
  273. annotations[pageIndex].push(annotation)
  274. }
  275. addAnnotations(annotation) {
  276. this.handleAnnotationChange({
  277. type: 'add',
  278. annotation: [annotation]
  279. })
  280. }
  281. delAnnotations(annotation) {
  282. this.handleAnnotationChange({
  283. type: 'delete',
  284. annotation: [annotation]
  285. })
  286. }
  287. addEvent(eventName, fn) {
  288. this.eventBus._on(eventName, fn);
  289. }
  290. removeEvent(eventName, fn) {
  291. this.eventBus._off(eventName, fn);
  292. }
  293. async loadDocument(file, options = {}) {
  294. if (this.pdfLoadingTask) {
  295. await this.close()
  296. }
  297. if (options.annotations) {
  298. parseAnnotationFromXml(options.annotations)
  299. }
  300. this.info = options.info || null
  301. this.pageChangedCallback = options.pageChangedCallback || this.pageChangedCallback
  302. this.scaleChangedCallback = options.scaleChangedCallback || this.scaleChangedCallback
  303. this.annotationsNumChangedCallback = options.annotationsNumChangedCallback || this.annotationsNumChangedCallback
  304. this.distanceChangedCallback = options.distanceChangedCallback || this.distanceChangedCallback
  305. annotationStore.annotationsAll = null
  306. annotationStore.selectedName = null
  307. this.fontFileInited = false
  308. const parameters = {
  309. cMapUrl: CMAP_URL,
  310. cMapPacked: true,
  311. enableXfa: true
  312. };
  313. if (typeof file === "string") {
  314. // URL
  315. parameters.url = file
  316. } else if (file && "byteLength" in file) {
  317. // ArrayBuffer
  318. parameters.data = file;
  319. } else if (file.url && file.originalUrl) {
  320. parameters.url = file.url;
  321. }
  322. // 获取pdf信息,返回promise
  323. const loadingTask = getDocument(parameters)
  324. this.pdfLoadingTask = loadingTask
  325. this._docName = options.filename || getPdfFilenameFromUrl(parameters.url)
  326. const getPwd = (pwd) => this.#pwd = pwd
  327. const handlePassword = (updateCallback, reason) => {
  328. if (this.#oldPwd && options.notUpdatePwd) {
  329. getPwd(this.#oldPwd);
  330. updateCallback(this.#oldPwd);
  331. loadingTask.onPassword = null;
  332. } else if (options.pwd) {
  333. getPwd(options.pwd);
  334. updateCallback(options.pwd);
  335. loadingTask.onPassword = null;
  336. } else {
  337. this.passwordPrompt.setUpdateCallback(updateCallback, reason, getPwd);
  338. this.passwordPrompt.open();
  339. }
  340. };
  341. loadingTask.onPassword = handlePassword;
  342. loadingTask.onProgress = ({ loaded, total }) => {
  343. const progress = options.progress || this.progress
  344. progress.call(this, loaded / total)
  345. }
  346. // notUploadPdf -> 仅预览 不上传到服务器
  347. // if (options.notUploadPdf) {
  348. // const pdfDocument = await loadingTask.promise;
  349. // await this.load(pdfDocument);
  350. // return this.#pwd
  351. // }
  352. // 处理传入的PDF
  353. return await loadingTask.promise.then(
  354. async pdfDocument => {
  355. // 上传pdf
  356. await pdfDocument.getData().then(async (binaryData) => {
  357. this.pdfDocument = pdfDocument
  358. if (!options.notUpdatePwd) {
  359. this.#oldPwd = this.#pwd
  360. }
  361. let buffer = new Uint8Array(binaryData)
  362. await this.messageHandler.sendWithPromise('LoadFile', {
  363. buffer,
  364. fontFile: this.#fonFile,
  365. fontName: 'DroidSansFallbackFull'
  366. })
  367. const loadRes = await this.messageHandler.sendWithPromise('LoadDocumentByStream', {
  368. doc: this.doc,
  369. fileId: 0,
  370. length: buffer.length,
  371. password: this.#pwd
  372. })
  373. this.contentEditAnnotationsManager.addTextEditor = (data) => {
  374. const pageNumber = data.pageNumber
  375. if (pageNumber > this.pagesCount || pageNumber < 1) {
  376. throw new Error({
  377. message: 'Invalid pageNumber'
  378. })
  379. }
  380. if (this.toolMode !== 'editor') {
  381. this.setToolMode('editor')
  382. }
  383. if (this.currentPageNumber !== pageNumber) {
  384. this.pdfViewer.scrollPageIntoView({ pageNumber: pageNumber })
  385. }
  386. const pageIndex = pageNumber - 1
  387. const pageView = this.pdfViewer._pages[pageIndex]
  388. if (pageView) {
  389. pageView.addTextEditor(data)
  390. }
  391. }
  392. this.contentEditAnnotationsManager.getEditAnnotation = async (pageNumber) => {
  393. if (pageNumber > this.pagesCount || pageNumber < 1) {
  394. throw new Error({
  395. message: 'Invalid pageNumber'
  396. })
  397. }
  398. if (this.toolMode !== 'editor') {
  399. this.setToolMode('editor')
  400. }
  401. if (this.currentPageNumber !== pageNumber) {
  402. this.pdfViewer.scrollPageIntoView({ pageNumber: pageNumber })
  403. }
  404. const pageIndex = pageNumber - 1
  405. const pageView = this.pdfViewer._pages[pageIndex]
  406. if (pageView) {
  407. const editAnnotation = await pageView.getEditAnnotation()
  408. return editAnnotation
  409. }
  410. }
  411. let annotations = null
  412. console.log(this.webviewerServer)
  413. await this.initPage()
  414. if (this.webviewerServer) {
  415. const formData = new FormData();
  416. formData.append('file', new Blob([binaryData], { type: 'application/pdf' }), this._docName);
  417. formData.append('password', this.#pwd);
  418. const data = {
  419. method: 'POST',
  420. headers: {
  421. 'Authorization': this._token
  422. },
  423. body: formData
  424. }
  425. await fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.uploadUrl, data)
  426. .then((res) => {
  427. return res.json()
  428. })
  429. .then((resp) => {
  430. if (resp.code === "200") {
  431. const data = resp.data
  432. this._pdfId = data.pdfId
  433. // const rawAnnotations = data.annotateJson && JSON.parse(data.annotateJson)
  434. const rawAnnotations = data.annotateJson && data.annotateJson
  435. console.log(rawAnnotations)
  436. annotations = this.convertAnnotation(rawAnnotations)
  437. } else if (resp.code === "319") {
  438. }
  439. })
  440. .catch((error) => {
  441. console.log(error)
  442. return { error: true, message: error.message }
  443. });
  444. } else {
  445. annotations = await this.getAnnotations()
  446. }
  447. console.log(annotations)
  448. annotations && this.initAnnotations(annotations)
  449. console.log(this.annotations)
  450. })
  451. await this.load(pdfDocument);
  452. return { pwd: !!this.#pwd };
  453. },
  454. reason => {
  455. if (loadingTask !== this.pdfLoadingTask) {
  456. return undefined; // Ignore errors for previously opened PDF files.
  457. }
  458. let key = "loading_error";
  459. if (reason instanceof InvalidPDFException) {
  460. key = "invalid_file_error";
  461. console.warn('Invalid or corrupted PDF file.')
  462. return new Promise(function (resolve, reject) {
  463. reject('invalid_file_error')
  464. });
  465. } else if (reason instanceof MissingPDFException) {
  466. key = "missing_file_error";
  467. console.warn('Missing PDF file.')
  468. } else if (reason instanceof UnexpectedResponseException) {
  469. key = "unexpected_response_error";
  470. console.warn('Unexpected server response.')
  471. } else if (reason) {
  472. if (reason.message === 'No password given') {
  473. key = "no_password_given";
  474. console.warn('No password given.')
  475. return new Promise(function (resolve, reject) {
  476. reject('no_password_given')
  477. });
  478. } else if (reason.message === 'Incorrect Password') {
  479. return new Promise(function (resolve, reject) {
  480. reject('incorrect_password')
  481. });
  482. }
  483. }
  484. throw new Error(key)
  485. }
  486. )
  487. }
  488. getSelectedText(pageNumber) {
  489. if (pageNumber) {
  490. const page = this.pdfViewer._pages[pageNumber - 1]
  491. if (page) {
  492. return page.selectedText
  493. }
  494. }
  495. return this.pdfViewer._pages.map(function(page) {
  496. return page.selectedText
  497. }).filter(function(text) {
  498. return text !== null
  499. }).join('\n')
  500. }
  501. convertAnnotation(rawAnnotations) {
  502. const annotations = []
  503. for (const type in rawAnnotations) {
  504. let annotationData = rawAnnotations[type]
  505. if (!Array.isArray(annotationData)) {
  506. annotationData = [annotationData]
  507. }
  508. for (let i = 0; i < annotationData.length; i++) {
  509. annotationData[i].type = type
  510. const annotation = this.#formatAnnotation(annotationData[i])
  511. annotations.push(annotation)
  512. }
  513. }
  514. return annotations
  515. }
  516. #formatRect(annotation) {
  517. const pageIndex = annotation.page
  518. const { height } = this.pagesPtr[pageIndex]
  519. const rect = annotation.rect.split(',')
  520. const left = round(rect[0], 2)
  521. const bottom = round((height - Number(rect[1])), 2)
  522. const right = round(rect[2], 2)
  523. const top = round((height - Number(rect[3])), 2)
  524. return {
  525. left,
  526. bottom,
  527. right,
  528. top
  529. }
  530. }
  531. #formatCoords(annotation) {
  532. const formattedCoords = []
  533. const pageIndex = annotation.page
  534. const { height } = this.pagesPtr[pageIndex]
  535. const coords = annotation.coords.split(',')
  536. for (let i = 0; (i + 7) < coords.length; i += 8) {
  537. formattedCoords.push({
  538. PointX: round(coords[i + 4], 2),
  539. PointY: round((height - Number(coords[i + 5])), 2)
  540. })
  541. formattedCoords.push({
  542. PointX: round(coords[i + 6], 2),
  543. PointY: round((height - Number(coords[i + 7])), 2)
  544. })
  545. formattedCoords.push({
  546. PointX: round(coords[i], 2),
  547. PointY: round((height - Number(coords[i + 1])), 2)
  548. })
  549. formattedCoords.push({
  550. PointX: round(coords[i + 2], 2),
  551. PointY: round((height - Number(coords[i + 3])), 2)
  552. })
  553. }
  554. return formattedCoords
  555. }
  556. #formatLinePoints(annotation) {
  557. const pageIndex = annotation.page
  558. const { height } = this.pagesPtr[pageIndex]
  559. const linePoints = []
  560. const start = annotation.start.split(',')
  561. const end = annotation.end.split(',')
  562. linePoints.push(round(start[0], 2))
  563. linePoints.push(round((height - Number(start[1])), 2))
  564. linePoints.push(round(end[0], 2))
  565. linePoints.push(round((height - Number(end[1])), 2))
  566. return linePoints
  567. }
  568. #formatInkPointes(annotation) {
  569. const pageIndex = annotation.page
  570. const { height } = this.pagesPtr[pageIndex]
  571. const inklist = []
  572. let inklistData = annotation.inklist.gesture
  573. if (!Array.isArray(inklistData)) {
  574. inklistData = [inklistData]
  575. }
  576. for (let i = 0; i < inklistData.length; i++) {
  577. if (inklistData[i][inklistData[i].length - 1] === ';') {
  578. inklistData[i] = inklistData[i].slice(0, inklistData[i].length - 1)
  579. }
  580. const points = inklistData[i].split(';').map((rawPoint) => {
  581. const point = rawPoint.split(',')
  582. return {
  583. PointX: round(point[0], 2),
  584. PointY: round((height - Number(point[1])), 2)
  585. }
  586. })
  587. inklist.push(points)
  588. }
  589. return inklist
  590. }
  591. #formatAnnotation(rawAnnotation) {
  592. const annotation = {}
  593. annotation.type = rawAnnotation.type
  594. rawAnnotation.rect && (annotation.rect = this.#formatRect(rawAnnotation))
  595. annotation.date = parseAdobePDFTimestamp(rawAnnotation.creationdate)
  596. annotation.pageIndex = Number(rawAnnotation.page)
  597. annotation.index = Number(rawAnnotation.index)
  598. annotation.content = rawAnnotation.contents || ''
  599. annotation.transparency = round(rawAnnotation.opacity, 2) || 1
  600. switch (rawAnnotation.type) {
  601. case 'freetext':
  602. let fontName = rawAnnotation.textStyle.fontName
  603. fontName = fontName[0].toUpperCase() + fontName.slice(1)
  604. annotation.fontName = fontName
  605. annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
  606. annotation.color = rawAnnotation.textStyle.fontColor
  607. annotation.textAlignment = rawAnnotation.textStyle.alignment
  608. annotation.content = rawAnnotation['contents-richtext'] || rawAnnotation.content
  609. if (rawAnnotation['contents-richtext']) {
  610. const parser = new DOMParser()
  611. const xmlDoc = parser.parseFromString(rawAnnotation['contents-richtext'], 'text/xml');
  612. const error = xmlDoc.getElementsByTagName("parsererror")
  613. if (error.length > 0) {
  614. annotation.content = rawAnnotation['contents-richtext']
  615. } else {
  616. annotation.content = xmlDoc.firstElementChild.innerText
  617. }
  618. }
  619. break
  620. case 'text':
  621. annotation.textColor = rawAnnotation.color
  622. break
  623. case 'highlight':
  624. case 'underline':
  625. case 'strikeout':
  626. case 'squiggly':
  627. annotation.color = rawAnnotation.color
  628. annotation.quadPoints = this.#formatCoords(rawAnnotation)
  629. break
  630. case 'line':
  631. annotation.linePoints = this.#formatLinePoints(rawAnnotation)
  632. annotation.tail = rawAnnotation.tail
  633. annotation.head = rawAnnotation.head
  634. annotation.borderColor = rawAnnotation.color
  635. annotation.lineWidth = round(rawAnnotation.width, 2)
  636. break
  637. case 'square':
  638. case 'circle':
  639. annotation.borderColor = rawAnnotation.color
  640. annotation.lineWidth = round(rawAnnotation.width, 2)
  641. rawAnnotation['interior-opacity'] && (annotation.fillTransparency = round(rawAnnotation['interior-opacity'], 2))
  642. rawAnnotation['interior-color'] && (annotation.fillColor = rawAnnotation['interior-color'])
  643. break
  644. case 'ink':
  645. annotation.color = rawAnnotation.color
  646. annotation.lineWidth = round(rawAnnotation.width, 2)
  647. annotation.inkPointes = this.#formatInkPointes(rawAnnotation)
  648. break
  649. case 'link':
  650. const linkAction = pushbuttonAction && pushbuttonAction.Action
  651. if (linkAction && linkAction.Dest && linkAction.Dest.XYZ) {
  652. annotation.destPage = Number(linkAction.Dest.XYZ.Page) + 1
  653. annotation.url = ''
  654. } else if (linkAction && linkAction.URI) {
  655. annotation.url = linkAction.URI.URI
  656. annotation.destPage = ''
  657. }
  658. break
  659. case 'stamp':
  660. annotation.content = rawAnnotation.icon
  661. rawAnnotation.image && (annotation.image = rawAnnotation.image)
  662. annotation.stampType = rawAnnotation['stamp-type']
  663. break
  664. case 'textfield':
  665. rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
  666. annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
  667. annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
  668. rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
  669. let textfieldFontName = rawAnnotation.textStyle.fontName
  670. textfieldFontName = textfieldFontName[0].toUpperCase() + textfieldFontName.slice(1)
  671. annotation.fontName = textfieldFontName
  672. annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
  673. annotation.color = rawAnnotation.textStyle.fontColor
  674. annotation.textAlignment = rawAnnotation.textStyle.alignment
  675. annotation.content = rawAnnotation.value
  676. annotation.fieldName = rawAnnotation.fieldname
  677. annotation.isBold = rawAnnotation.textStyle.blod === 'true'
  678. annotation.isItalic = rawAnnotation.textStyle.italic === 'true'
  679. annotation.isMultiLine = rawAnnotation.textStyle.multiLine === 'true' ? 1 : 0
  680. annotation.isHidden = (!rawAnnotation.flags || rawAnnotation.flags === 'invisible') ? 1 : 0
  681. break
  682. case 'checkbox':
  683. case 'radiobutton':
  684. rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
  685. annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
  686. annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
  687. rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
  688. annotation.fieldName = rawAnnotation.fieldname
  689. annotation.isHidden = (!rawAnnotation.flags || rawAnnotation.flags === 'invisible') ? 1 : 0
  690. annotation.isChecked = rawAnnotation.value === 'Yes' ? 1 : 0
  691. annotation.checkStyle = Number(rawAnnotation.styleCA)
  692. break
  693. case 'combobox':
  694. case 'listbox':
  695. rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
  696. annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
  697. annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
  698. rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
  699. annotation.fieldName = rawAnnotation.fieldname
  700. let comboboxFontName = rawAnnotation.textStyle.fontName
  701. comboboxFontName = comboboxFontName[0].toUpperCase() + comboboxFontName.slice(1)
  702. annotation.fontName = comboboxFontName
  703. annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
  704. annotation.color = rawAnnotation.textStyle.fontColor
  705. annotation.isBold = rawAnnotation.textStyle.blod === 'true'
  706. annotation.isItalic = rawAnnotation.textStyle.italic === 'true'
  707. annotation.isMultiLine = rawAnnotation.textStyle.multiLine === 'true' ? 1 : 0
  708. annotation.isHidden = !rawAnnotation.flags && rawAnnotation.flags === 'invisible' ? 1 : 0
  709. annotation.items = this.#getItems(rawAnnotation)
  710. annotation.selected = round(rawAnnotation.select, 0)
  711. break
  712. case 'pushbutton':
  713. const pushbuttonAction = rawAnnotation.OnActivation && rawAnnotation.OnActivation.Action
  714. if (pushbuttonAction && pushbuttonAction.URI) {
  715. annotation.url = pushbuttonAction.URI.URI
  716. annotation.destPage = ''
  717. annotation.actionType = 6
  718. } else if (pushbuttonAction && pushbuttonAction.Dest && pushbuttonAction.Dest.XYZ) {
  719. annotation.destPage = Number(pushbuttonAction.Dest.XYZ.Page) + 1
  720. annotation.url = ''
  721. annotation.actionType = 1
  722. }
  723. rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
  724. annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
  725. annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
  726. rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
  727. annotation.fieldName = rawAnnotation.fieldname
  728. if (rawAnnotation.textStyle.fontName) {
  729. let pushbuttonFontName = rawAnnotation.textStyle.fontName
  730. pushbuttonFontName = pushbuttonFontName[0].toUpperCase() + pushbuttonFontName.slice(1)
  731. annotation.fontName = pushbuttonFontName
  732. } else {
  733. annotation.fontName = 'Helvetica'
  734. }
  735. annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
  736. annotation.color = rawAnnotation.textStyle.fontColor
  737. annotation.isBold = rawAnnotation.textStyle.blod === 'true'
  738. annotation.isItalic = rawAnnotation.textStyle.italic === 'true'
  739. annotation.title = rawAnnotation.styleCA
  740. annotation.isHidden = !rawAnnotation.flags && rawAnnotation.flags === 'invisible' ? 1 : 0
  741. break
  742. }
  743. return annotation
  744. }
  745. #getItems(rawAnnotation) {
  746. const items = []
  747. const opt = rawAnnotation.opt
  748. for (let i = 0; i < opt.length; i++) {
  749. items.push({
  750. Value: opt[i].value,
  751. String: opt[i].key
  752. })
  753. }
  754. return items
  755. }
  756. getOutlines() {
  757. if (this.outlines) {
  758. return this.outlines
  759. }
  760. }
  761. scrollPageIntoView({
  762. pageNumber,
  763. }) {
  764. // if (this.currentPage)
  765. }
  766. async search(value) {
  767. const searchResults = await this.messageHandler.sendWithPromise('Search', {
  768. pagesPtr: this.pagesPtr,
  769. value
  770. })
  771. this.searchResults = searchResults
  772. this.eventBus.dispatch('search', searchResults)
  773. if (!searchResults.length) {
  774. this.clearSearchResults()
  775. this.#activeSearchIndex = 0
  776. } else {
  777. this.setActiveSearchResult()
  778. }
  779. return searchResults
  780. }
  781. setActiveSearchResult(result = null, activeSearchIndex = 0) {
  782. if (!this.searchResults) return
  783. const activeResult = result ? result : this.searchResults[0]
  784. const quad = activeResult.quads[0]
  785. const left = quad.left * this.scale
  786. const top = quad.top * this.scale
  787. const pageView = this.pdfViewer._pages[activeResult.pageNum - 1]
  788. this.pdfViewer.currentPageNumber = activeResult.pageNum
  789. scrollIntoView(pageView.div, {
  790. left,
  791. top
  792. })
  793. if (result) {
  794. const preActiveSearchResult = this.searchResults[this.#activeSearchIndex]
  795. this.pdfViewer._pages[preActiveSearchResult.pageNum - 1].clearActiveSearchResult(preActiveSearchResult)
  796. pageView.setActiveSearchResult(result)
  797. this.#activeSearchIndex = activeSearchIndex
  798. } else {
  799. pageView.setActiveSearchResult(activeResult)
  800. this.#activeSearchIndex = 0
  801. }
  802. }
  803. clearSearchResults() {
  804. for (let i = 0; i < this.pdfViewer._pages.length; i++) {
  805. const _page = this.pdfViewer._pages[i]
  806. _page.clearSearchResults()
  807. }
  808. this.searchResults = null
  809. }
  810. async initPage() {
  811. const pagesCount = await this.messageHandler.sendWithPromise("GetPageCount", {
  812. doc: this.doc,
  813. })
  814. this._pagesCount = pagesCount
  815. this.pagesPtr = []
  816. for (let pageIndex = 0; pageIndex < pagesCount; pageIndex++) {
  817. const page = await this.messageHandler.sendWithPromise("GetPageSize", {
  818. doc: this.doc,
  819. pageIndex
  820. })
  821. const textPtr = await this.messageHandler.sendWithPromise('InitText', {
  822. pagePtr: page.pagePtr
  823. })
  824. this.pagesPtr.push({
  825. doc: this.doc,
  826. pagePtr: page.pagePtr,
  827. textPtr,
  828. width: page.width,
  829. height: page.height
  830. })
  831. }
  832. }
  833. async getAnnotations() {
  834. const annotations = []
  835. const pagesPtr = this.pagesPtr
  836. for (let pageIndex = 0; pageIndex < this.pagesCount; pageIndex++) {
  837. const page = pagesPtr[pageIndex]
  838. const data = await this.messageHandler.sendWithPromise('InitAnnot', {
  839. pageIndex,
  840. pagePtr: page.pagePtr
  841. })
  842. for (let annotCountNum = 0; annotCountNum < data.annotCount; annotCountNum++) {
  843. const annotation = data.annotations[annotCountNum]
  844. const typeInt = annotation.type
  845. const type = AnnotationTypeString[typeInt]
  846. annotation.pageIndex = pageIndex
  847. annotation.type = type
  848. let attr = null
  849. if (type === 'widget') {
  850. attr = await this.messageHandler.sendWithPromise('GetWidgetAnnotation', {
  851. doc: this.doc,
  852. annotPtr: annotation.annotPtr,
  853. pagePtr: annotation.pagePtr,
  854. typeInt
  855. })
  856. } else {
  857. attr = await this.messageHandler.sendWithPromise('GetAnnotation', {
  858. doc: this.doc,
  859. annotPtr: annotation.annotPtr,
  860. pagePtr: annotation.pagePtr,
  861. typeInt,
  862. scale: this.scale
  863. })
  864. }
  865. Object.assign(annotation, attr)
  866. annotations.push(annotation)
  867. }
  868. }
  869. this.pdfViewer.pagesPtr = this.pagesPtr
  870. return annotations
  871. }
  872. async reRenderAnnotations() {
  873. this.annotations = null
  874. const annotations = []
  875. const pagesPtr = this.pagesPtr
  876. for (let pageIndex = 0; pageIndex < pagesPtr.length; pageIndex++) {
  877. const pagePtr = pagesPtr[pageIndex]
  878. const data = await this.messageHandler.sendWithPromise('InitAnnot', {
  879. pageIndex,
  880. pagePtr: pagePtr.pagePtr
  881. })
  882. for (let annotCountNum = 0; annotCountNum < data.annotCount; annotCountNum++) {
  883. const annotation = data.annotations[annotCountNum]
  884. const typeInt = annotation.type
  885. const type = AnnotationTypeString[typeInt]
  886. annotation.pageIndex = pageIndex
  887. annotation.type = type
  888. let attr = null
  889. if (type === 'widget') {
  890. attr = await this.messageHandler.sendWithPromise('GetWidgetAnnotation', {
  891. doc: this.doc,
  892. annotPtr: annotation.annotPtr,
  893. pagePtr: annotation.pagePtr,
  894. typeInt
  895. })
  896. } else {
  897. attr = await this.messageHandler.sendWithPromise('GetAnnotation', {
  898. doc: this.doc,
  899. annotPtr: annotation.annotPtr,
  900. pagePtr: annotation.pagePtr,
  901. typeInt,
  902. scale: this.scale
  903. })
  904. }
  905. Object.assign(annotation, attr)
  906. annotations.push(annotation)
  907. }
  908. }
  909. for (let index = 0; index < annotations.length; index++) {
  910. if (!this.annotations) {
  911. this.annotations = {}
  912. }
  913. this.pushAnnotations(annotations[index])
  914. this.pdfViewer.renderAnnotation(annotations[index])
  915. }
  916. this.eventBus.dispatch('annotationChanged', { annotations: this.annotations })
  917. }
  918. get supportsFullscreen() {
  919. const fullscreenEnabled = document.webkitFullscreenEnabled || document.mozFullscreenEnabled || document.fullscreenEnabled
  920. return shadow(this, "supportsFullscreen", fullscreenEnabled);
  921. }
  922. removeAllAnnotations() {
  923. if (this.pdfViewer.annotationStorage) {
  924. this.pdfViewer.annotationStorage.cleanup()
  925. }
  926. }
  927. async importAnnotations(data) {
  928. const source = await new Promise((resolve) => {
  929. const reader = new FileReader();
  930. reader.onload = (event) => {
  931. const contents = event.target.result
  932. resolve(contents)
  933. };
  934. if (this.webviewerServer) {
  935. reader.readAsText(data);
  936. } else {
  937. reader.readAsArrayBuffer(data);
  938. }
  939. });
  940. if (this.webviewerServer) {
  941. const annotationsXml = parseAnnotationFromXml(source)
  942. if (!annotationsXml.length) return
  943. this.handleAnnotationChange({
  944. type: 'add',
  945. annotation: annotationsXml
  946. })
  947. } else {
  948. const xfdfBuffer = new Uint8Array(source)
  949. await this.messageHandler.sendWithPromise('XFDFImportAnnotations', {
  950. doc: this.doc,
  951. xfdfBuffer
  952. })
  953. }
  954. this.emptyAnnotations()
  955. this.reRenderAnnotations()
  956. // for (let i = 0; i < len; i++) {
  957. // const item = annotationsXml[i]
  958. // const data = {
  959. // annotationType: 3,
  960. // fontSize: 10,
  961. // value: item.obj_attr.content,
  962. // rotation: 0,
  963. // position: item.obj_attr.position,
  964. // type: 'custom'
  965. // }
  966. // this.pdfViewer._pages[annotationsXml[i].obj_attr.page].pdfAnnotationLayer.deserialize(data)
  967. // }
  968. }
  969. saveAnnotations() {
  970. if (!this.pdfDocument || !this.info) return
  971. let append_objects = []
  972. for (let [key, value] of this.pdfViewer.annotationStorage._storage) {
  973. append_objects.push(value.annotationObj);
  974. }
  975. this.uploadAnnotations({
  976. append_objects,
  977. tid: this.info.tid
  978. })
  979. }
  980. initApiUrl(urls) {
  981. this.optionUrl = urls
  982. }
  983. setPassword(value) {
  984. if (this.webviewerServer) {
  985. const options = {
  986. method: 'POST',
  987. headers: {
  988. "Content-Type": "application/json",
  989. 'Authorization': this._token
  990. },
  991. body: JSON.stringify({
  992. pdfId: this._pdfId,
  993. annotateHandles: [{
  994. operate: 'set-password',
  995. userPassword: value
  996. }]
  997. }),
  998. }
  999. return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.editUrl, options)
  1000. .then((res) => {
  1001. return res.json()
  1002. })
  1003. .then((data) => {
  1004. if (data.code === "200") {
  1005. return true
  1006. } else {
  1007. return false
  1008. }
  1009. })
  1010. .catch((error) => {
  1011. console.log(error)
  1012. return false
  1013. });
  1014. } else {
  1015. // 设置密码标志
  1016. this.saveAction = 'set'
  1017. this.#pwd = value
  1018. return true
  1019. }
  1020. }
  1021. removePassword() {
  1022. if (this.webviewerServer) {
  1023. const options = {
  1024. method: 'POST',
  1025. headers: {
  1026. "Content-Type": "application/json",
  1027. 'Authorization': this._token
  1028. },
  1029. body: JSON.stringify({
  1030. pdfId: this._pdfId,
  1031. annotateHandles: [{
  1032. operate: 'remove-password'
  1033. }]
  1034. }),
  1035. }
  1036. return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.editUrl, options)
  1037. .then((res) => {
  1038. return res.json()
  1039. })
  1040. .then((data) => {
  1041. if (data.code === "200") {
  1042. return true
  1043. } else {
  1044. return false
  1045. }
  1046. })
  1047. .catch((error) => {
  1048. console.log(error)
  1049. return false
  1050. });
  1051. } else {
  1052. if (this.#pwd) {
  1053. // 移除密码标志
  1054. this.saveAction = 'remove'
  1055. this.#pwd = ''
  1056. }
  1057. return true
  1058. }
  1059. }
  1060. getOptionUrl() {
  1061. return this.optionUrl
  1062. }
  1063. uploadAnnotations(data) {
  1064. const options = {
  1065. method: 'POST',
  1066. headers: {
  1067. Accept: 'application/json',
  1068. 'Content-type': 'application/json',
  1069. },
  1070. }
  1071. if (!data.append_objects.length) return
  1072. options.body = JSON.stringify(data)
  1073. fetch(this.optionUrl.baseUrl + this.optionUrl.saveAnnotations + '?f=' + this.info.token, options)
  1074. .then((res) => {
  1075. alert('Save Success')
  1076. return res.json()
  1077. })
  1078. .then((resp) => resp)
  1079. .catch((error) => ({ error: true, message: error.message }));
  1080. }
  1081. toggleSidebar() {
  1082. this.pdfSidebar.toggle()
  1083. }
  1084. // 渲染PDF
  1085. async load(pdfDocument) {
  1086. this.pdfLinkService.setDocument(pdfDocument);
  1087. const pdfViewer = this.pdfViewer;
  1088. pdfViewer.setDocument(pdfDocument, this.annotations, this.pagesPtr);
  1089. const { firstPagePromise, onePageRendered, pagesPromise } = pdfViewer;
  1090. pdfDocument.getDownloadInfo().then(({ length }) => {
  1091. this._contentLength = length; // Ensure that the correct length is used.
  1092. this.downloadComplete = true;
  1093. firstPagePromise.then(() => {
  1094. this.eventBus.dispatch("documentloaded", { source: this });
  1095. });
  1096. })
  1097. if (this.pdfThumbnailViewer) {
  1098. const pdfThumbnailViewer = this.pdfThumbnailViewer;
  1099. pdfThumbnailViewer.setDocument(pdfDocument);
  1100. }
  1101. const doc = this.doc
  1102. const messageHandler = this.messageHandler
  1103. const outlines = await messageHandler.sendWithPromise('GetOutlines', {
  1104. doc
  1105. })
  1106. const generateOutline = (outline, index, parent) => {
  1107. const outlineItem = new Outline({
  1108. outline,
  1109. index,
  1110. doc,
  1111. messageHandler,
  1112. parent
  1113. })
  1114. outline.children.forEach(function (outline, index) {
  1115. outlineItem.children.push(generateOutline(outline, index, outlineItem))
  1116. })
  1117. return outlineItem
  1118. }
  1119. outlines.forEach((outline, index) => {
  1120. const outlineItem = generateOutline(outline, index, null)
  1121. this.outlines.push(outlineItem)
  1122. })
  1123. firstPagePromise.then(pdfPage => {
  1124. let hash = null;
  1125. let rotation = null;
  1126. let sidebarView = 0
  1127. let scrollMode = -1
  1128. let spreadMode = -1
  1129. this.setInitialView(hash, {
  1130. rotation,
  1131. sidebarView,
  1132. scrollMode,
  1133. spreadMode,
  1134. });
  1135. })
  1136. this.eventBus.dispatch("documentinit", { source: this });
  1137. }
  1138. initBindEvents() {
  1139. const { eventBus, _boundEvents } = this;
  1140. eventBus._on("scalechanging", this.webViewerScaleChanging.bind(this));
  1141. }
  1142. // 绑定自定义事件
  1143. bindEvents() {
  1144. const { eventBus, _boundEvents } = this;
  1145. eventBus._on("resize", this.webViewerResize.bind(this));
  1146. eventBus._on("pagerendered", this.webViewerPageRendered.bind(this));
  1147. eventBus._on("updateviewarea", this.webViewerUpdateViewarea.bind(this));
  1148. eventBus._on("pagechanging", this.webViewerPageChanging.bind(this));
  1149. eventBus._on("rotationchanging", this.webViewerRotationChanging.bind(this));
  1150. eventBus._on("sidebarviewchanged", this.webViewerSidebarViewChanged.bind(this));
  1151. eventBus._on("presentationmodechanged", this.webViewerPresentationModeChanged.bind(this));
  1152. eventBus._on("presentationmode", this.webViewerPresentationMode.bind(this));
  1153. eventBus._on("nextpage", this.webViewerNextPage.bind(this));
  1154. eventBus._on("previouspage", this.webViewerPreviousPage.bind(this));
  1155. eventBus._on("zoomin", this.webViewerZoomIn.bind(this));
  1156. eventBus._on("zoomout", this.webViewerZoomOut.bind(this));
  1157. eventBus._on("pagenumberchanged", this.webViewerPageNumberChanged.bind(this));
  1158. eventBus._on("scalechanged", this.webViewerScaleChanged.bind(this));
  1159. eventBus._on("rotatecw", this.webViewerRotateCw.bind(this));
  1160. eventBus._on("rotateccw", this.webViewerRotateCcw.bind(this));
  1161. eventBus._on("switchscrollmode", this.webViewerSwitchScrollMode.bind(this));
  1162. eventBus._on("scrollmodechanged", this.webViewerScrollModeChanged.bind(this));
  1163. eventBus._on("switchspreadmode", this.webViewerSwitchSpreadMode.bind(this));
  1164. eventBus._on("spreadmodechanged", this.webViewerSpreadModeChanged.bind(this));
  1165. eventBus._on("findfromurlhash", this.webViewerFindFromUrlHash.bind(this));
  1166. eventBus._on("updatefindmatchescount", this.webViewerUpdateFindMatchesCount.bind(this));
  1167. eventBus._on("updatefindcontrolstate", this.webViewerUpdateFindControlState.bind(this));
  1168. eventBus._on("fileinputchange", this.webViewerFileInputChange.bind(this));
  1169. eventBus._on("openfile", this.webViewerOpenFile.bind(this));
  1170. eventBus._on("switchannotationeditormode", this.webViewerSwitchAnnotationEditorMode.bind(this));
  1171. eventBus._on("annotationsCountChanged", this.webViewerAnnotationsCountChanged.bind(this))
  1172. eventBus._on("distanceChanged", this.webViewerDistanceChanged.bind(this));
  1173. eventBus._on("annotationChange", this.handleAnnotationChange.bind(this));
  1174. eventBus._on("createSignature", this.handleCreateSignature.bind(this));
  1175. eventBus._on("handleField", this.handleField.bind(this));
  1176. eventBus._on("pageNumberChanged", this.pageNumberChanged.bind(this));
  1177. }
  1178. bindWindowEvents() {
  1179. const { eventBus, _boundEvents } = this;
  1180. _boundEvents.windowResize = () => {
  1181. eventBus.dispatch("resize", { source: window });
  1182. };
  1183. _boundEvents.windowHashChange = () => {
  1184. eventBus.dispatch("hashchange", {
  1185. source: window,
  1186. hash: document.location.hash.substring(1),
  1187. });
  1188. };
  1189. _boundEvents.windowUpdateFromSandbox = event => {
  1190. eventBus.dispatch("updatefromsandbox", {
  1191. source: window,
  1192. detail: event.detail,
  1193. });
  1194. };
  1195. window.addEventListener("resize", _boundEvents.windowResize);
  1196. window.addEventListener("hashchange", _boundEvents.windowHashChange);
  1197. window.addEventListener(
  1198. "updatefromsandbox",
  1199. _boundEvents.windowUpdateFromSandbox
  1200. );
  1201. }
  1202. async close() {
  1203. if (!this.pdfLoadingTask) {
  1204. return
  1205. }
  1206. const promises = [];
  1207. promises.push(this.pdfLoadingTask.destroy());
  1208. this.pdfLoadingTask = null
  1209. if (this.pdfDocument) {
  1210. this.pdfDocument = null;
  1211. this.pdfThumbnailViewer?.setDocument(null);
  1212. this.pdfViewer.setDocument(null);
  1213. this.pdfLinkService.setDocument(null);
  1214. }
  1215. this.isInitialViewSet = false;
  1216. this.downloadComplete = false;
  1217. this.url = "";
  1218. this.baseUrl = "";
  1219. this._downloadUrl = "";
  1220. this.documentInfo = null;
  1221. this.metadata = null;
  1222. this._contentDispositionFilename = null;
  1223. this._contentLength = null;
  1224. this._saveInProgress = false;
  1225. this._hasAnnotationEditors = false;
  1226. this.pdfSidebar?.reset();
  1227. this.pdfOutlineViewer?.reset();
  1228. this.pdfAttachmentViewer?.reset();
  1229. this.outlines = []
  1230. this.#pwd = ''
  1231. this._pdfId = null
  1232. this.annotations = null
  1233. await Promise.all(promises);
  1234. }
  1235. handleInk(annotation) {
  1236. let rawAnnotation = JSON.parse(JSON.stringify(annotation))
  1237. let inklist = ''
  1238. let inkArray = []
  1239. if (Array.isArray(rawAnnotation.inklist)) {
  1240. inkArray = rawAnnotation.inklist
  1241. }
  1242. else {
  1243. inkArray.push(rawAnnotation.inklist)
  1244. }
  1245. for (let i = 0; i < inkArray.length; i++) {
  1246. inklist = inklist + inkArray[i].replaceAll(';', ',') + '//'
  1247. }
  1248. rawAnnotation.inklist = inklist// rawAnnotation.inklist.replaceAll(';', ',') + '//'
  1249. return rawAnnotation
  1250. }
  1251. async handleAnnotationChange(data) {
  1252. let annotation = data.annotation
  1253. this.annotationHistory.push(annotation)
  1254. let annotateHandles = []
  1255. const formTypes = ['textfield', 'checkbox', 'radiobutton', 'listbox', 'combobox', 'pushbutton']
  1256. if (data.type === 'add') {
  1257. if (!Array.isArray(annotation)) {
  1258. annotation = [annotation]
  1259. }
  1260. const length = annotation.length
  1261. for (let i = 0; i < length; i++) {
  1262. if (Number(annotation[i].pageIndex) + 1 > this.pagesCount) continue
  1263. if (formTypes.includes(annotation[i].type)) {
  1264. annotation[i].operate = "add-form"
  1265. } else {
  1266. annotation[i].operate = "add-annot"
  1267. }
  1268. await this.handleAnnotations(annotation[i])
  1269. if (this.pdfViewer) {
  1270. this.pdfViewer.renderAnnotation(annotation[i], !!data.show)
  1271. }
  1272. annotation[i].targetPage = annotation[i].pageIndex * 1 + 1
  1273. let currentAnnotation = JSON.parse(JSON.stringify(annotation[i]))
  1274. if (currentAnnotation.inklist) {
  1275. currentAnnotation = this.handleInk(currentAnnotation)
  1276. }
  1277. annotateHandles.push(currentAnnotation)
  1278. }
  1279. } else {
  1280. const annotations = this.annotations[annotation.pageIndex]
  1281. if (!annotations) return
  1282. const index = findIndex(annotation.name, annotations)
  1283. if (this.webviewerServer) {
  1284. annotation.index = index + 1
  1285. }
  1286. if (data.type === 'delete') {
  1287. annotations.splice(index, 1)
  1288. if (!annotations.length) {
  1289. delete this.annotations[annotation.pageIndex]
  1290. }
  1291. if (!this.webviewerServer) {
  1292. this.messageHandler.sendWithPromise('RemoveAnnot', {
  1293. annotPtr: annotation.annotPtr
  1294. })
  1295. }
  1296. } else if (data.type === 'empty') {
  1297. annotations.splice(index, 1)
  1298. if (!annotations.length) {
  1299. delete this.annotations[annotation.pageIndex]
  1300. }
  1301. return
  1302. } else {
  1303. if (!this.webviewerServer) {
  1304. annotation.doc = this.doc
  1305. this.messageHandler.sendWithPromise('EditAnnotation', {
  1306. annotation
  1307. })
  1308. }
  1309. const rawAnnotation = annotations[index]
  1310. annotations[index] = {
  1311. ...rawAnnotation,
  1312. ...annotation
  1313. }
  1314. }
  1315. annotation.targetPage = annotation.pageIndex + 1
  1316. let currentAnnotation = annotation
  1317. if (currentAnnotation.inklist) {
  1318. currentAnnotation = this.handleInk(currentAnnotation)
  1319. }
  1320. annotateHandles.push(currentAnnotation)
  1321. }
  1322. this.eventBus.dispatch('annotationChanged', { annotations: this.annotations })
  1323. if (this.webviewerServer) {
  1324. this.#convertAnnotationsForBackend(annotateHandles)
  1325. const options = {
  1326. method: 'POST',
  1327. headers: {
  1328. "Content-Type": "application/json",
  1329. 'Authorization': this._token
  1330. },
  1331. body: JSON.stringify({
  1332. pdfId: this._pdfId,
  1333. annotateHandles
  1334. }),
  1335. }
  1336. return await fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.editUrl, options)
  1337. .then((res) => {
  1338. return res.json()
  1339. })
  1340. .then((data) => {
  1341. if (data.code === "200") {
  1342. return true
  1343. } else {
  1344. return false
  1345. }
  1346. })
  1347. .catch((error) => (console.log(error)));
  1348. }
  1349. return true
  1350. }
  1351. #convertAnnotationsForBackend(annotations) {
  1352. console.log(annotations)
  1353. for (let i =0; i < annotations.length; i++) {
  1354. const annotation = annotations[i]
  1355. switch (annotation.type) {
  1356. case 'freetext':
  1357. annotation.fillColor = annotation.bgColor
  1358. delete annotation.bgColor
  1359. break
  1360. }
  1361. for (let key in annotation) {
  1362. switch (key) {
  1363. case 'rect':
  1364. annotation.rect = this.#formatRectForBackend(annotation.rect, annotation.pageIndex)
  1365. break
  1366. case 'linePoints':
  1367. annotation.linePoints = this.#formatLinePointsForBackend(annotation.linePoints, annotation.pageIndex)
  1368. break
  1369. case 'borderWidth':
  1370. annotation.lineWidth = annotation.borderWidth
  1371. break
  1372. case 'textAlignment':
  1373. annotation.alignment = annotation.textAlignment
  1374. delete annotation.textAlignment
  1375. break
  1376. case 'stampType':
  1377. if (annotation.stampType === 'standard') {
  1378. annotation.standardStampType = annotation.content
  1379. } else if (annotation.stampType === 'text') {
  1380. annotation.textStampFirststring = annotation.content
  1381. annotation.textStampSecondstring = annotation.time
  1382. annotation.textStampColor = annotation.stampColor
  1383. annotation.textStampShape = annotation.stampShape
  1384. delete annotation.time
  1385. delete annotation.stampColor
  1386. delete annotation.stampShape
  1387. } else if (annotation.stampType === 'image') {
  1388. annotation.type = 'image'
  1389. delete annotation.annotPtr
  1390. delete annotation.imageData
  1391. delete annotation.pagePtr
  1392. }
  1393. delete annotation.content
  1394. break
  1395. case 'inkPointes':
  1396. const { height } = this.pagesPtr[annotation.pageIndex]
  1397. const inkPointes = annotation.inkPointes
  1398. let points = ''
  1399. for (let i = 0; i < inkPointes.length; i++) {
  1400. const inkPoint = inkPointes[i]
  1401. for (let j = 0; j + 1 < inkPoint.length; j+=2) {
  1402. if (j === 0) {
  1403. points+=inkPoint[j].PointX
  1404. }
  1405. points+=`,${height - inkPoint[j + 1].PointY}`
  1406. }
  1407. points+='//'
  1408. }
  1409. delete annotation.inkPointes
  1410. annotation.inklist = points
  1411. break
  1412. }
  1413. }
  1414. }
  1415. }
  1416. #formatRectForBackend(rect, pageIndex) {
  1417. const { height } = this.pagesPtr[pageIndex]
  1418. const { left, top: rawTop, right, bottom: rawBottom } = rect
  1419. const top = height - rawTop
  1420. const bottom = height - rawBottom
  1421. return `${left},${bottom},${right},${top}`
  1422. }
  1423. #formatLinePointsForBackend(linePoints, pageIndex) {
  1424. const { height } = this.pagesPtr[pageIndex]
  1425. const top = height - linePoints[1]
  1426. const bottom = height - linePoints[3]
  1427. return `${linePoints[0]},${top},${linePoints[2]},${bottom}`
  1428. }
  1429. emptyAnnotations() {
  1430. const annotations = this.annotations
  1431. if (this.annotations) {
  1432. for (let pageIndex in annotations) {
  1433. this.pdfViewer._pages[pageIndex].emptyAnnotations()
  1434. }
  1435. }
  1436. }
  1437. handleCreateSignature(data) {
  1438. this.addAnnotations(data)
  1439. }
  1440. webViewerDistanceChanged(evt) {
  1441. this.distanceChangedCallback(evt.distance)
  1442. }
  1443. progress(level) {
  1444. if (this.downloadComplete) {
  1445. // Don't accidentally show the loading bar again when the entire file has
  1446. // already been fetched (only an issue when disableAutoFetch is enabled).
  1447. return
  1448. }
  1449. const percent = Math.round(level * 100);
  1450. // When we transition from full request to range requests, it's possible
  1451. // that we discard some of the loaded data. This can cause the loading
  1452. // bar to move backwards. So prevent this by only updating the bar if it
  1453. // increases.
  1454. if (percent <= this.percent) {
  1455. return
  1456. }
  1457. this.percent = percent;
  1458. }
  1459. async flattenPdfDownload() {
  1460. if (this._token && this._pdfId) {
  1461. const data = {
  1462. method: 'POST',
  1463. headers: {
  1464. "Content-Type": "application/json",
  1465. 'Authorization': this._token
  1466. },
  1467. body: JSON.stringify({
  1468. pdfId: this._pdfId
  1469. })
  1470. }
  1471. return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.flattenUrl, data)
  1472. .then(async (res) => {
  1473. const type = res.headers.get("content-type")
  1474. if (type.startsWith("application/json")) {
  1475. const errorObj = await res.json();
  1476. return Promise.reject(errorObj);
  1477. } else {
  1478. return res.blob()
  1479. }
  1480. })
  1481. .then((data) => {
  1482. saveAs(data, this._docName)
  1483. return true
  1484. })
  1485. .catch((error) => {
  1486. console.log(error)
  1487. return false
  1488. });
  1489. } else {
  1490. let saveType = 2
  1491. if (!this.saveAction || this.saveAction === 'set') {
  1492. saveType = 2
  1493. } else if (this.saveAction === 'remove') {
  1494. saveType = 3
  1495. }
  1496. const blobData = await this.messageHandler.sendWithPromise('FlattenPage', {
  1497. doc: this.doc,
  1498. pagesPtr: this.pagesPtr,
  1499. saveType,
  1500. password: this.#pwd,
  1501. oldPassword: this.#oldPwd
  1502. })
  1503. saveAs(blobData, this._docName)
  1504. return true
  1505. }
  1506. }
  1507. async download(download = false, data, type) {
  1508. if (data) {
  1509. data.forEach(file => {
  1510. saveAs(file.url, file.fileName)
  1511. })
  1512. } else if (this._token && this._pdfId) {
  1513. const data = {
  1514. method: 'POST',
  1515. headers: {
  1516. "Content-Type": "application/json",
  1517. 'Authorization': this._token
  1518. },
  1519. body: JSON.stringify({
  1520. pdfId: this._pdfId
  1521. })
  1522. }
  1523. return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.saveUrl, data)
  1524. .then(async (res) => {
  1525. const type = res.headers.get("content-type")
  1526. if (type.startsWith("application/json")) {
  1527. const errorObj = await res.json();
  1528. return Promise.reject(errorObj);
  1529. } else {
  1530. return res.blob()
  1531. }
  1532. })
  1533. .then((data) => {
  1534. if (download) {
  1535. saveAs(data, this._docName)
  1536. }
  1537. return data
  1538. })
  1539. .catch((error) => {
  1540. console.log(error)
  1541. return false
  1542. });
  1543. } else {
  1544. let saveType = 2
  1545. if (!this.saveAction || this.saveAction === 'set') {
  1546. saveType = 2
  1547. } else if (this.saveAction === 'remove') {
  1548. saveType = 3
  1549. }
  1550. const blobData = await this.messageHandler.sendWithPromise('SaveDocumentByStream', {
  1551. doc: this.doc,
  1552. saveType: type || saveType,
  1553. password: this.#pwd,
  1554. oldPassword: this.#oldPwd
  1555. })
  1556. if (download) {
  1557. saveAs(blobData, this._docName)
  1558. }
  1559. return blobData
  1560. }
  1561. }
  1562. async exportXfdf(download = true) {
  1563. const xfdf = await this.messageHandler.sendWithPromise('XFDFExportAnnotations', {
  1564. doc: this.doc
  1565. })
  1566. const blob = new Blob([xfdf], { type: 'application/vnd.adobe.xfdf' })
  1567. if (download) {
  1568. const name = this._docName.replace(/\.pdf$/, '.xfdf')
  1569. saveAs(blob, name)
  1570. }
  1571. return blob
  1572. return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.downloadAnnotation + "?pdfId=" + this._pdfId, {
  1573. method: 'GET',
  1574. headers: {
  1575. "Content-Type": "application/json",
  1576. 'Authorization': this._token
  1577. }
  1578. })
  1579. .then(async (res) => {
  1580. const type = res.headers.get("content-type")
  1581. if (type.startsWith("application/json")) {
  1582. const errorObj = await res.json();
  1583. return Promise.reject(errorObj);
  1584. } else {
  1585. return res.blob()
  1586. }
  1587. })
  1588. .then((data) => {
  1589. const name = this._docName.replace(/\.pdf$/, '.xfdf')
  1590. saveAs(data, name)
  1591. return true
  1592. })
  1593. .catch((error) => {
  1594. console.log(error)
  1595. return false
  1596. });
  1597. }
  1598. _initializeViewerComponents({
  1599. container,
  1600. viewer,
  1601. thumbnailView,
  1602. annotationView,
  1603. findbarView,
  1604. toggleButton,
  1605. }) {
  1606. this.viewerContainer = viewer
  1607. const pdfRenderingQueue = new PDFRenderingQueue();
  1608. pdfRenderingQueue.onIdle = this._cleanup.bind(this);
  1609. this.pdfRenderingQueue = pdfRenderingQueue;
  1610. const pdfLinkService = new PDFLinkService();
  1611. this.pdfLinkService = pdfLinkService;
  1612. this.pdfViewer = new PDFViewer({
  1613. container,
  1614. viewer,
  1615. messageHandler: this.messageHandler,
  1616. annotationStore,
  1617. tool: {
  1618. tool: this.activeTool,
  1619. color: this.color
  1620. },
  1621. annotationView,
  1622. renderingQueue: pdfRenderingQueue,
  1623. linkService: pdfLinkService,
  1624. renderer: 'canvas',
  1625. textLayerMode: 1,
  1626. enablePrintAutoRotate: true,
  1627. eventBus: this.eventBus,
  1628. $t: this.$t,
  1629. doc: this.doc,
  1630. messageHandler: this.messageHandler
  1631. });
  1632. pdfRenderingQueue.setViewer(this.pdfViewer);
  1633. pdfLinkService.setViewer(this.pdfViewer);
  1634. if (thumbnailView) {
  1635. this.pdfThumbnailViewer = new PDFThumbnailViewer({
  1636. container: thumbnailView,
  1637. renderingQueue: pdfRenderingQueue,
  1638. linkService: pdfLinkService
  1639. });
  1640. pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
  1641. }
  1642. this.pdfCursorTools = new PDFCursorTools({
  1643. container,
  1644. eventBus: this.eventBus,
  1645. cursorToolOnLoad: 0,
  1646. });
  1647. if (this.supportsFullscreen) {
  1648. this.pdfPresentationMode = new PDFPresentationMode({
  1649. container,
  1650. pdfViewer: this.pdfViewer,
  1651. eventBus: this.eventBus,
  1652. });
  1653. }
  1654. this.passwordPrompt = new PasswordPrompt(
  1655. {
  1656. dialog: document.getElementById("passwordDialog"),
  1657. label: document.getElementById("passwordText"),
  1658. input: document.getElementById("password"),
  1659. submitButton: document.getElementById("passwordSubmit"),
  1660. cancelButton: document.getElementById("passwordCancel"),
  1661. $t: this.$t
  1662. }
  1663. );
  1664. if (toggleButton) {
  1665. this.pdfSidebar = new PDFSidebar({
  1666. elements: {
  1667. toggleButton
  1668. },
  1669. pdfViewer: this.pdfViewer,
  1670. pdfThumbnailViewer: this.pdfThumbnailViewer,
  1671. eventBus: this.eventBus
  1672. });
  1673. this.pdfSidebar.onToggled = this.forceRendering.bind(this);
  1674. }
  1675. }
  1676. setInitialView(
  1677. storedHash,
  1678. { rotation, sidebarView, scrollMode, spreadMode } = {}
  1679. ) {
  1680. const setRotation = angle => {
  1681. if (isValidRotation(angle)) {
  1682. this.pdfViewer.pagesRotation = angle;
  1683. }
  1684. };
  1685. const setViewerModes = (scroll, spread) => {
  1686. if (isValidScrollMode(scroll)) {
  1687. this.pdfViewer.scrollMode = scroll;
  1688. }
  1689. if (isValidSpreadMode(spread)) {
  1690. this.pdfViewer.spreadMode = spread;
  1691. }
  1692. };
  1693. this.isInitialViewSet = true;
  1694. // this.pdfSidebar.setInitialView(sidebarView);
  1695. setViewerModes(scrollMode, spreadMode);
  1696. if (!this.pdfViewer.currentScaleValue) {
  1697. // Scale was not initialized: invalid bookmark or scale was not specified.
  1698. // Setting the default one.
  1699. this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
  1700. }
  1701. this.pdfViewer.forceRendering()
  1702. }
  1703. requestFullScreenMode() {
  1704. this.pdfPresentationMode?.request();
  1705. }
  1706. /**
  1707. * @private
  1708. */
  1709. _cleanup() {
  1710. if (!this.pdfDocument) {
  1711. return; // run cleanup when document is loaded
  1712. }
  1713. this.pdfViewer.cleanup();
  1714. this.pdfThumbnailViewer?.cleanup();
  1715. // We don't want to remove fonts used by active page SVGs.
  1716. this.pdfDocument.cleanup(
  1717. /* keepLoadedFonts = */ this.pdfViewer.renderer === 'svg'
  1718. );
  1719. }
  1720. cleanup() {
  1721. this._cleanup()
  1722. }
  1723. zoomIn(steps) {
  1724. if (this.pdfViewer.isInPresentationMode) {
  1725. return;
  1726. }
  1727. this.pdfViewer.increaseScale({
  1728. drawingDelay: 400
  1729. });
  1730. }
  1731. zoomOut(steps) {
  1732. if (this.pdfViewer.isInPresentationMode) {
  1733. return;
  1734. }
  1735. this.pdfViewer.decreaseScale({
  1736. drawingDelay: 400
  1737. });
  1738. }
  1739. nextPage() {
  1740. return this.pdfViewer.nextPage()
  1741. }
  1742. previousPage() {
  1743. return this.pdfViewer.previousPage()
  1744. }
  1745. pageNumberChanged(value) {
  1746. // Note that for `<input type="number">` HTML elements, an empty string will
  1747. // be returned for non-number inputs; hence we simply do nothing in that case.
  1748. if (value !== "") {
  1749. this.pdfLinkService.goToPage(value);
  1750. }
  1751. // Ensure that the page number input displays the correct value, even if the
  1752. // value entered by the user was invalid (e.g. a floating point number).
  1753. if (
  1754. value !== this.pdfViewer.currentPageNumber.toString() &&
  1755. value !== this.pdfViewer.currentPageLabel
  1756. ) {
  1757. this.toolbar && this.toolbar.setPageNumber(
  1758. pdfViewer.currentPageNumber,
  1759. pdfViewer.currentPageLabel
  1760. );
  1761. }
  1762. }
  1763. scrollTo({
  1764. left,
  1765. top
  1766. }) {
  1767. scrollIntoView(this.viewerContainer, {
  1768. left,
  1769. top
  1770. })
  1771. }
  1772. webViewerAnnotationsCountChanged(evt) {
  1773. this.annotationsNumChangedCallback(evt.annotationsCount);
  1774. }
  1775. forceRendering() {
  1776. this.pdfRenderingQueue.printing = !!this.printService;
  1777. this.pdfRenderingQueue.isThumbnailViewEnabled =
  1778. this.pdfSidebar.visibleView === SidebarView.THUMBS;
  1779. this.pdfRenderingQueue.renderHighestPriority();
  1780. }
  1781. webViewerResize() {
  1782. const { pdfDocument, pdfViewer, pdfRenderingQueue } = this;
  1783. if (pdfRenderingQueue.printing && window.matchMedia("print").matches) {
  1784. // Work-around issue 15324 by ignoring "resize" events during printing.
  1785. return;
  1786. }
  1787. if (!pdfDocument) {
  1788. return;
  1789. }
  1790. console.log('resize')
  1791. const currentScaleValue = pdfViewer.currentScaleValue;
  1792. if (
  1793. currentScaleValue === "auto" ||
  1794. currentScaleValue === "page-fit" ||
  1795. currentScaleValue === "page-width"
  1796. ) {
  1797. // Note: the scale is constant for 'page-actual'.
  1798. pdfViewer.resize(currentScaleValue)
  1799. }
  1800. // pdfViewer.update();
  1801. }
  1802. webViewerPageRendered({ pageNumber, error }) {
  1803. // If the page is still visible when it has finished rendering,
  1804. // ensure that the page number input loading indicator is hidden.
  1805. /** if (pageNumber === this.page) {
  1806. this.toolbar.updateLoadingIndicatorState(false);
  1807. } */
  1808. // Use the rendered page to set the corresponding thumbnail image.
  1809. if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) {
  1810. const pageView = this.pdfViewer.getPageView(
  1811. /* index = */ pageNumber - 1
  1812. );
  1813. const thumbnailView = this.pdfThumbnailViewer.getThumbnail(
  1814. /* index = */ pageNumber - 1
  1815. );
  1816. if (pageView && thumbnailView) {
  1817. thumbnailView.setImage(pageView);
  1818. }
  1819. }
  1820. }
  1821. get annotationMode() {
  1822. return this._annotationMode
  1823. }
  1824. set annotationMode(mode) {
  1825. this._annotationMode = mode;
  1826. }
  1827. webViewerSwitchAnnotationEditorMode(evt) {
  1828. this.pdfViewer.annotationEditorMode = evt.mode;
  1829. }
  1830. switchTool(mode) {
  1831. this.pdfCursorTools.switchTool(mode);
  1832. }
  1833. webViewerUpdateViewarea({ location }) {
  1834. if (this.isInitialViewSet) {
  1835. // Only update the storage when the document has been loaded *and* rendered.
  1836. this.store
  1837. ?.setMultiple({
  1838. page: location.pageNumber,
  1839. zoom: location.scale,
  1840. scrollLeft: location.left,
  1841. scrollTop: location.top,
  1842. rotation: location.rotation,
  1843. })
  1844. .catch(() => {
  1845. // Unable to write to storage.
  1846. });
  1847. }
  1848. if (this.#textSearch) {
  1849. this.#textSearch.updateMatch()
  1850. }
  1851. }
  1852. webViewerScrollModeChanged(evt) {
  1853. if (
  1854. this.isInitialViewSet &&
  1855. !this.pdfViewer.isInPresentationMode
  1856. ) {
  1857. // Only update the storage when the document has been loaded *and* rendered.
  1858. this.store?.set("scrollMode", evt.mode).catch(() => {
  1859. // Unable to write to storage.
  1860. });
  1861. }
  1862. }
  1863. webViewerScaleChanging(evt) {
  1864. // this.toolbar.setPageScale(evt.presetValue, evt.scale);
  1865. // this.pdfViewer.update();
  1866. this.scaleChangedCallback && this.scaleChangedCallback(evt.scale)
  1867. }
  1868. webViewerRotationChanging(evt) {
  1869. this.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
  1870. this.forceRendering();
  1871. // Ensure that the active page doesn't change during rotation.
  1872. this.pdfViewer.currentPageNumber = evt.pageNumber;
  1873. }
  1874. webViewerPageChanging({ pageNumber, pageLabel }) {
  1875. // this.toolbar.setPageNumber(pageNumber, pageLabel);
  1876. // this.secondaryToolbar.setPageNumber(pageNumber);
  1877. if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) {
  1878. this.pdfThumbnailViewer.scrollThumbnailIntoView(pageNumber);
  1879. }
  1880. this.pageChangedCallback(this.page)
  1881. }
  1882. webViewerSidebarViewChanged({ view }) {
  1883. this.pdfRenderingQueue.isThumbnailViewEnabled =
  1884. view === SidebarView.THUMBS;
  1885. if (this.isInitialViewSet) {
  1886. // Only update the storage when the document has been loaded *and* rendered.
  1887. this.store?.set("sidebarView", view).catch(() => {
  1888. // Unable to write to storage.
  1889. });
  1890. }
  1891. }
  1892. webViewerPageMode({ mode }) {
  1893. // Handle the 'pagemode' hash parameter, see also `PDFLinkService_setHash`.
  1894. let view;
  1895. switch (mode) {
  1896. case "thumbs":
  1897. view = SidebarView.THUMBS;
  1898. break;
  1899. case "bookmarks":
  1900. case "outline": // non-standard
  1901. view = SidebarView.OUTLINE;
  1902. break;
  1903. case "attachments": // non-standard
  1904. view = SidebarView.ATTACHMENTS;
  1905. break;
  1906. case "layers": // non-standard
  1907. view = SidebarView.LAYERS;
  1908. break;
  1909. case "none":
  1910. view = SidebarView.NONE;
  1911. break;
  1912. default:
  1913. console.error('Invalid "pagemode" hash parameter: ' + mode);
  1914. return;
  1915. }
  1916. this.pdfSidebar.switchView(view, /* forceOpen = */ true);
  1917. }
  1918. async webViewerNamedAction(evt) {
  1919. // Processing a couple of named actions that might be useful, see also
  1920. // `PDFLinkService.executeNamedAction`.
  1921. switch (evt.action) {
  1922. case "GoToPage":
  1923. this.appConfig.toolbar.pageNumber.select();
  1924. break;
  1925. case "Print":
  1926. const url = await this.download(false, null, 3)
  1927. this.triggerPrinting(url);
  1928. return url
  1929. break;
  1930. case "SaveAs":
  1931. this.downloadOrSave();
  1932. break;
  1933. }
  1934. }
  1935. triggerPrinting(data) {
  1936. let url = data instanceof Blob ? URL.createObjectURL(data) : data
  1937. url = decodeURIComponent(url)
  1938. printJS({
  1939. url,
  1940. printable: url,
  1941. type: 'pdf',
  1942. showModal: false
  1943. });
  1944. }
  1945. webViewerPresentationModeChanged(evt) {
  1946. this.pdfViewer.presentationModeState = evt.state;
  1947. }
  1948. webViewerPresentationMode() {
  1949. this.requestPresentationMode();
  1950. }
  1951. webViewerNextPage() {
  1952. this.pdfViewer.nextPage();
  1953. }
  1954. webViewerPreviousPage() {
  1955. this.pdfViewer.previousPage();
  1956. }
  1957. webViewerZoomIn() {
  1958. this.zoomIn();
  1959. }
  1960. webViewerZoomOut() {
  1961. this.zoomOut();
  1962. }
  1963. webViewerPageNumberChanged(evt) {
  1964. const pdfViewer = this.pdfViewer;
  1965. // Note that for `<input type="number">` HTML elements, an empty string will
  1966. // be returned for non-number inputs; hence we simply do nothing in that case.
  1967. if (evt.value !== "") {
  1968. this.pdfLinkService.goToPage(evt.value);
  1969. }
  1970. // Ensure that the page number input displays the correct value, even if the
  1971. // value entered by the user was invalid (e.g. a floating point number).
  1972. if (
  1973. evt.value !== pdfViewer.currentPageNumber.toString() &&
  1974. evt.value !== pdfViewer.currentPageLabel
  1975. ) {
  1976. this.toolbar.setPageNumber(
  1977. pdfViewer.currentPageNumber,
  1978. pdfViewer.currentPageLabel
  1979. );
  1980. }
  1981. }
  1982. webViewerScaleChanged(value) {
  1983. this.pdfViewer.currentScaleValue = value;
  1984. }
  1985. webViewerRotateCw() {
  1986. this.rotatePages(90);
  1987. }
  1988. webViewerRotateCcw() {
  1989. this.rotatePages(-90);
  1990. }
  1991. webViewerSwitchScrollMode(mode) {
  1992. this.pdfViewer.scrollMode = mode;
  1993. }
  1994. webViewerSwitchSpreadMode(mode) {
  1995. this.pdfViewer.spreadMode = mode;
  1996. }
  1997. rotatePages(delta) {
  1998. this.pdfViewer.pagesRotation += delta;
  1999. // Note that the thumbnail viewer is updated, and rendering is triggered,
  2000. // in the 'rotationchanging' event handler.
  2001. }
  2002. webViewerSpreadModeChanged(evt) {
  2003. if (
  2004. this.isInitialViewSet &&
  2005. !this.pdfViewer.isInPresentationMode
  2006. ) {
  2007. // Only update the storage when the document has been loaded *and* rendered.
  2008. this.store?.set("spreadMode", evt.mode).catch(() => {
  2009. // Unable to write to storage.
  2010. });
  2011. }
  2012. }
  2013. webViewerFindFromUrlHash(evt) {
  2014. this.eventBus.dispatch("find", {
  2015. source: evt.source,
  2016. type: "",
  2017. query: evt.query,
  2018. phraseSearch: evt.phraseSearch,
  2019. caseSensitive: false,
  2020. entireWord: false,
  2021. highlightAll: true,
  2022. findPrevious: false,
  2023. matchDiacritics: true,
  2024. });
  2025. }
  2026. webViewerUpdateFindMatchesCount({ matchesCount }) {
  2027. if (this.supportsIntegratedFind) {
  2028. this.externalServices.updateFindMatchesCount(matchesCount);
  2029. } else {
  2030. this.findBar.updateResultsCount(matchesCount);
  2031. }
  2032. }
  2033. webViewerUpdateFindControlState({
  2034. state,
  2035. previous,
  2036. matchesCount,
  2037. rawQuery,
  2038. }) {
  2039. if (this.supportsIntegratedFind) {
  2040. this.externalServices.updateFindControlState({
  2041. result: state,
  2042. findPrevious: previous,
  2043. matchesCount,
  2044. rawQuery,
  2045. });
  2046. } else {
  2047. this.findBar.updateUIState(state, previous, matchesCount);
  2048. }
  2049. }
  2050. webViewerFileInputChange(evt) {
  2051. if (this.pdfViewer?.isInPresentationMode) {
  2052. return; // Opening a new PDF file isn't supported in Presentation Mode.
  2053. }
  2054. const file = evt.fileInput.files[0];
  2055. let url = URL.createObjectURL(file);
  2056. if (file.name) {
  2057. url = { url, originalUrl: file.name };
  2058. }
  2059. this.open(url);
  2060. };
  2061. // eslint-disable-next-line no-var
  2062. webViewerOpenFile(evt) {
  2063. const fileInput = this.appConfig.openFileInput;
  2064. fileInput.click();
  2065. }
  2066. async setToolMode(mode) {
  2067. const oldMode = this.toolMode;
  2068. this.toolMode = mode;
  2069. if (mode === 'editor' && !this.fontFileInited) {
  2070. await this.initFontFile()
  2071. }
  2072. this.eventBus.dispatch("toolModeChanged", mode);
  2073. if (oldMode === 'editor' && this.toolMode !== 'editor') {
  2074. await this.updateTextPtr();
  2075. }
  2076. for (let page in this.annotations) {
  2077. for (let i = 0; i < this.annotations[page].length; i++) {
  2078. const annot = this.annotations[page][i]
  2079. const element = document.getElementById(annot['name'])
  2080. if (element) {
  2081. if (this.toolMode !== 'form') {
  2082. if (annot.isHidden == 1) {
  2083. element.style.display = 'none';
  2084. element.style.pointerEvents = 'none';
  2085. } else if (annot.isHidden == 0) {
  2086. element.style.display = 'block';
  2087. element.style.pointerEvents = 'auto';
  2088. }
  2089. } else {
  2090. element.style.display = 'block';
  2091. element.style.pointerEvents = 'auto';
  2092. }
  2093. }
  2094. }
  2095. }
  2096. }
  2097. async updateTextPtr() {
  2098. await this.messageHandler.sendWithPromise('ClearPage', {
  2099. doc: this.doc
  2100. })
  2101. for (let pageIndex = 0; pageIndex < this.pagesCount; pageIndex++) {
  2102. await this.messageHandler.sendWithPromise('ClearText', {
  2103. textPtr: this.pagesPtr[pageIndex].textPtr
  2104. })
  2105. const pageSize = await this.messageHandler.sendWithPromise("GetPageSize", {
  2106. doc: this.doc,
  2107. pageIndex
  2108. })
  2109. const textPtr = await this.messageHandler.sendWithPromise('InitText', {
  2110. pagePtr: pageSize.pagePtr
  2111. })
  2112. this.pagesPtr[pageIndex].textPtr = textPtr
  2113. this.pagesPtr[pageIndex].pagePtr = pageSize.pagePtr
  2114. }
  2115. this.pdfViewer.pagesPtr = this.pagesPtr
  2116. this.pdfViewer._pages.forEach(page => {
  2117. page.pagesPtr = this.pagesPtr
  2118. });
  2119. this.pdfViewer.refresh()
  2120. }
  2121. setPropertyPanel(props) {
  2122. this.eventBus.dispatch("propertyPanelChanged", props);
  2123. }
  2124. setTextProperty(props) {
  2125. this.eventBus.dispatch("textPropertyChanged", props);
  2126. }
  2127. setInitProperty() {
  2128. if (this.activeTool === 'textfield') {
  2129. this.eventBus.dispatch("initTextfieldName");
  2130. } else if (this.activeTool === 'checkbox') {
  2131. this.eventBus.dispatch("initCheckboxName");
  2132. } else if (this.activeTool === 'radiobutton') {
  2133. this.eventBus.dispatch("initRadioButtonName");
  2134. } else if (this.activeTool === 'pushbutton') {
  2135. this.eventBus.dispatch("initPushButtonName");
  2136. }
  2137. }
  2138. handleField(prop) {
  2139. const id = prop.id
  2140. const key = prop.key
  2141. const value = prop.value
  2142. if (!id) return
  2143. let annotationsAll = Object.values(annotationStore.annotationsAll).reduce(function (acc, curr) {
  2144. return acc.concat(curr);
  2145. }, []);
  2146. let targetObj = annotationsAll.find(obj => obj.name === id)
  2147. if (key && (value || value === 0)) {
  2148. let props = {
  2149. name: id
  2150. }
  2151. props[key] = value
  2152. this.eventBus.dispatch("setProperty", props)
  2153. }
  2154. return targetObj
  2155. }
  2156. handleSign(flag, param) {
  2157. if (flag === 'create' && !this.InkSign) {
  2158. this.InkSign = new InkSign({
  2159. pdfViewer: this.pdfViewer,
  2160. eventBus: this.eventBus,
  2161. })
  2162. }
  2163. if (!this.InkSign) return;
  2164. if (flag === 'clear' || flag === 'create') {
  2165. this.InkSign.clear()
  2166. }
  2167. if (flag === 'save') {
  2168. this.InkSign.toImage(param)
  2169. }
  2170. if (flag === 'reset') {
  2171. this.InkSign.reset()
  2172. this.InkSign = null
  2173. }
  2174. if (flag === "update") {
  2175. this.InkSign.update(param)
  2176. }
  2177. }
  2178. handleStamp(data) {
  2179. if (!data) return
  2180. let imgUi = data.stampContainer
  2181. let pageNum = data.page
  2182. let pageView = this.pdfViewer.getPageView(pageNum - 1)
  2183. let rect = null
  2184. let annotData = null
  2185. if (pageView && imgUi) {
  2186. let pageWidth = pageView.viewport.viewBox[2]
  2187. let pageHeight = pageView.viewport.viewBox[3]
  2188. let imgWidth = imgUi.width
  2189. let imgHeight = imgUi.height
  2190. let left = (pageWidth - imgWidth) / 2
  2191. let top = (pageHeight - imgHeight) / 2
  2192. let right = (pageWidth + imgWidth) / 2
  2193. let bottom = (pageHeight + imgHeight) / 2
  2194. rect = {
  2195. left,
  2196. top,
  2197. right,
  2198. bottom,
  2199. }
  2200. }
  2201. if (data.stampType === 'standard') {
  2202. annotData = {
  2203. operate: 'add-annot',
  2204. type: 'stamp',
  2205. pageIndex: pageNum - 1,
  2206. rect,
  2207. stampColor: 'white',
  2208. date: new Date(),
  2209. stampType: 'standard',
  2210. content: imgUi.alt
  2211. }
  2212. }
  2213. if (data.stampType === 'dynamic') {
  2214. annotData = {
  2215. operate: 'add-annot',
  2216. type: 'stamp',
  2217. date: new Date(),
  2218. pageIndex: pageNum - 1,
  2219. // rect,
  2220. content: data.text,
  2221. time: data.time,
  2222. stampColor: data.color,
  2223. stampType: 'text'
  2224. }
  2225. }
  2226. annotData.stampShape = 0
  2227. this.addAnnotations(annotData)
  2228. }
  2229. async compare(data) {
  2230. if (this.webviewerServer) {
  2231. const formData = new FormData()
  2232. for (let key in data) {
  2233. formData.append(key, data[key])
  2234. }
  2235. const options = {
  2236. method: 'POST',
  2237. headers: {
  2238. 'Authorization': this._token
  2239. },
  2240. body: formData
  2241. }
  2242. return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.compareUrl, options)
  2243. .then(async (res) => {
  2244. const type = res.headers.get("content-type")
  2245. if (type.startsWith("application/json")) {
  2246. const errorObj = await res.json();
  2247. return Promise.reject(errorObj);
  2248. } else {
  2249. const filename = res.headers.get("Content-Disposition").split("filename=")[1];
  2250. return { filename, blobData: res.blob(), type };
  2251. }
  2252. })
  2253. .then(async ({ filename, blobData, type }) => {
  2254. if (type === 'application/zip') {
  2255. return await unzipAndReadFiles(blobData)
  2256. } else {
  2257. // return blobData.then(blob => {
  2258. // const reader = new FileReader();
  2259. // reader.onload = function(event) {
  2260. // const content = event.target.result;
  2261. // console.log(content); // 打印blobData的内容
  2262. // };
  2263. // reader.readAsDataURL(blob);
  2264. // return { filename, url: URL.createObjectURL(blob) };
  2265. // })
  2266. return blobData.then(blob => ({
  2267. filename,
  2268. url: URL.createObjectURL(blob)
  2269. }));
  2270. }
  2271. })
  2272. .then((resp) => resp)
  2273. .catch((error) => ({ error: true, message: error.message }));
  2274. } else {
  2275. const res = await this.messageHandler.sendWithPromise('CompareDocument', {
  2276. data
  2277. })
  2278. if (data.type === 1) {
  2279. return [{
  2280. filename: data.leftFile.name.replace(/(\.pdf)/, `_${this.$t('compare.byComPDFKit')}.pdf`),
  2281. url: URL.createObjectURL(res[0])
  2282. }, {
  2283. filename: data.rightFile.name.replace(/(\.pdf)/, `_${this.$t('compare.byComPDFKit')}.pdf`),
  2284. url: URL.createObjectURL(res[1])
  2285. }, {
  2286. filename: this.$t('compare.byComPDFKit') + '.pdf',
  2287. url: URL.createObjectURL(res[2])
  2288. }
  2289. ]
  2290. } else if (data.type === 2) {
  2291. return {
  2292. filename: this._docName,
  2293. url: URL.createObjectURL(res)
  2294. }
  2295. }
  2296. // const { oldData, newData } = res
  2297. // let oldBlobData = new Blob(oldData, { type: "application/pdf" })
  2298. // saveAs(oldBlobData, 'old' + this._docName)
  2299. // let newBlobData = new Blob(newData, { type: "application/pdf" })
  2300. // saveAs(newBlobData, 'new' + this._docName)
  2301. }
  2302. }
  2303. async checkPassword(file) {
  2304. const parameters = {
  2305. cMapUrl: CMAP_URL,
  2306. cMapPacked: true,
  2307. enableXfa: true
  2308. };
  2309. if (typeof file === "string") {
  2310. // URL
  2311. parameters.url = file
  2312. } else if (file && "byteLength" in file) {
  2313. // ArrayBuffer
  2314. parameters.data = file;
  2315. } else if (file.url && file.originalUrl) {
  2316. parameters.url = file.url;
  2317. }
  2318. const loadingTask = getDocument(parameters)
  2319. this.pdfLoadingTask = loadingTask
  2320. this.#pwd = ''
  2321. const getPwd = (pwd) => this.#pwd = pwd
  2322. loadingTask.onPassword = (updateCallback, reason) => {
  2323. this.passwordPrompt.setUpdateCallback(updateCallback, reason, getPwd);
  2324. this.passwordPrompt.open();
  2325. };
  2326. return await loadingTask.promise.then(() => {
  2327. if (this.#pwd) return this.#pwd
  2328. return ''
  2329. }).catch((error) => {
  2330. return false
  2331. })
  2332. }
  2333. handleCreateStatus({
  2334. bool,
  2335. fileData
  2336. }) {
  2337. annotationStore.creating = bool
  2338. annotationStore.fileData = fileData
  2339. }
  2340. async initFontFile() {
  2341. try {
  2342. this.pdfViewer.setFontFile(this.#fonFile)
  2343. this.fontFileInited = true
  2344. } catch (error) {
  2345. console.log(error)
  2346. }
  2347. }
  2348. }
  2349. class PDFWorker {
  2350. destroyed = false
  2351. constructor() {
  2352. this._promiseCapability = new PromiseExt()
  2353. this._messageHandler = null
  2354. this._webWorker = null
  2355. this._initialize()
  2356. }
  2357. _initialize() {
  2358. try {
  2359. const workerSrc = "./lib/PDFWorker.js"
  2360. const worker = new Worker(workerSrc)
  2361. const messageHandler = new MessageHandler('main', 'worker', worker)
  2362. this._messageHandler = messageHandler
  2363. const terminateEarly = () => {
  2364. worker.removeEventListener("error", onWorkerError)
  2365. messageHandler.destroy()
  2366. worker.terminate()
  2367. if (this.destroyed) {
  2368. this._promiseCapability.reject(new Error("Worker was destroyed"))
  2369. } else {
  2370. console.error("The worker has been disabled.")
  2371. }
  2372. }
  2373. const onWorkerError = () => {
  2374. if (!this._webWorker) {
  2375. // Worker failed to initialize due to an error. Clean up and fall
  2376. // back to the fake worker.
  2377. terminateEarly();
  2378. }
  2379. }
  2380. worker.addEventListener("error", onWorkerError)
  2381. messageHandler.on("test", (data) => {
  2382. worker.removeEventListener("error", onWorkerError)
  2383. if (this.destroyed) {
  2384. terminateEarly();
  2385. return; // worker was destroyed
  2386. }
  2387. if (data) {
  2388. this._messageHandler = messageHandler
  2389. this._webWorker = worker
  2390. this._promiseCapability.resolve(true);
  2391. }
  2392. })
  2393. messageHandler.on("ready", data => {
  2394. worker.removeEventListener("error", onWorkerError);
  2395. if (this.destroyed) {
  2396. terminateEarly();
  2397. return; // worker was destroyed
  2398. }
  2399. try {
  2400. sendTest();
  2401. messageHandler.send("Ready", true)
  2402. } catch {
  2403. console.error("The worker has been disabled.")
  2404. }
  2405. })
  2406. const sendTest = () => {
  2407. const testObj = new Uint8Array();
  2408. // Ensure that we can use `postMessage` transfers.
  2409. messageHandler.send("test", testObj);
  2410. }
  2411. sendTest()
  2412. } catch (error) {
  2413. console.log(error)
  2414. console.log("The worker has been disabled.")
  2415. }
  2416. }
  2417. get promise() {
  2418. return this._promiseCapability.promise;
  2419. }
  2420. get messageHandler() {
  2421. return this._messageHandler;
  2422. }
  2423. destroy() {
  2424. this.destroyed = true
  2425. if (this._webWorker) {
  2426. // We need to terminate only web worker created resource.
  2427. this._webWorker.terminate()
  2428. this._webWorker = null
  2429. }
  2430. if (this._messageHandler) {
  2431. this._messageHandler.destroy()
  2432. this._messageHandler = null
  2433. }
  2434. }
  2435. }
  2436. // 解压缩zip文件
  2437. function unzipAndReadFiles(zipBlob) {
  2438. return new Promise((resolve, reject) => {
  2439. const jzip = new JSZip();
  2440. jzip.loadAsync(zipBlob)
  2441. .then((zipFiles) => {
  2442. const filePromises = Object.keys(zipFiles.files).map(fileName => {
  2443. return zipFiles.file(fileName).async("uint8array").then(fileData => {
  2444. const blob = new Blob([fileData], { type: 'application/octet-stream' });
  2445. const url = URL.createObjectURL(blob);
  2446. return { fileName, url };
  2447. });
  2448. });
  2449. Promise.all(filePromises)
  2450. .then(resolve)
  2451. .catch(reject);
  2452. })
  2453. .catch((error) => {
  2454. reject(error);
  2455. });
  2456. });
  2457. }
  2458. export default ComPDFKitViewer