index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <template>
  2. <div class="container_all">
  3. <!-- ///:style="{ transform: `scale(${scale})` }" @page-loaded="onPageLoaded" -->
  4. <div class="container_public">
  5. <div v-for="pageNumber in loadedPages" :key="pageNumber">
  6. <vue-pdf
  7. class="container_pdf"
  8. :key="`${pageNumber}===rrr`"
  9. :src="{
  10. url: fileUrl,
  11. cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.9.359/cmaps/',
  12. cMapPacked: true,
  13. }"
  14. :page="pageNumber"
  15. @rendered="handlePageRendered"
  16. ></vue-pdf>
  17. </div>
  18. </div>
  19. <img
  20. v-if="loadAll"
  21. src="../../static/explain/down_up.png"
  22. class="absolute_image1"
  23. @click="download"
  24. />
  25. <!-- <img
  26. v-if="loadAll"
  27. src="../../static/explain/scale_in.png"
  28. class="absolute_image2"
  29. @click="scaleIn"
  30. />
  31. <img
  32. v-if="loadAll"
  33. src="../../static/explain/scale_out.png"
  34. class="absolute_image3"
  35. @click="scaleOut"
  36. /> -->
  37. <!-- 全屏遮罩层 -->
  38. <div
  39. v-show="isLoading"
  40. class="fullscreen-loader"
  41. :style="{ zIndex: zIndex }"
  42. >
  43. <!-- 加载动画 -->
  44. <div class="loader">
  45. <div class="spinner"></div>
  46. <p class="tip">{{ text }}</p>
  47. </div>
  48. </div>
  49. </div>
  50. </template>
  51. <script>
  52. import { detail } from "@/api/explain.js";
  53. import VuePdf from "vue-pdf";
  54. export default {
  55. components: {
  56. VuePdf,
  57. },
  58. data() {
  59. return {
  60. loadAll: false,
  61. name: "",
  62. fileUrl: "",
  63. fileName: "",
  64. currentPage: 1,
  65. numPages: 0,
  66. scale: 1,
  67. loadedPages: 0,
  68. isLoading: false,
  69. text: "拼命加载中...",
  70. zIndex: 9999,
  71. };
  72. },
  73. onLoad(e) {
  74. var that = this;
  75. that.id = e.id;
  76. // uni.showLoading({
  77. // title: "加载中...",
  78. // mask: true,
  79. // });
  80. // uni.hideLoading();
  81. that.getDetail();
  82. },
  83. methods: {
  84. // 滚动加载逻辑
  85. // {"type":"scroll","timeStamp":24324.79999999702,"detail":{},
  86. // "target":{"id":"","offsetLeft":0,"offsetTop":0,"dataset":{}},
  87. // "currentTarget":{"id":"","offsetLeft":0,"offsetTop":0,"dataset":{}},"touches":[],
  88. // "changedTouches":[],"mp":{"@warning":"mp is deprecated","type":"scroll",
  89. // "timeStamp":24324.79999999702,"detail":{},"target":{"id":"","offsetLeft":0,"offsetTop":0,"dataset":{}},
  90. // "currentTarget":{"id":"","offsetLeft":0,"offsetTop":0,"dataset":{}},"touches":[],"changedTouches":[]},
  91. // "_processed":true}
  92. handleScroll(e) {
  93. // const target = e.target;
  94. // var offsetTop = target.offsetTop;
  95. // // 滚动到底部且未加载完所有页
  96. // if (this.loadedPages < this.numPages) {
  97. // this.loadedPages += 1; // 加载下一页
  98. // }
  99. },
  100. ///接口获取数据
  101. getDetail() {
  102. var that = this;
  103. var id = that.id;
  104. detail(id).then((res) => {
  105. if (res.code === 0) {
  106. that.name = res.data.name;
  107. var fileUrl = res.data.fileUrl;
  108. that.getPdfPages(fileUrl);
  109. } else {
  110. that.isLoading = false;
  111. }
  112. });
  113. },
  114. async getPdfPages(fileUrl) {
  115. var that = this;
  116. try {
  117. const loadingTask = VuePdf.createLoadingTask({
  118. url: fileUrl,
  119. cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.9.359/cmaps/",
  120. cMapPacked: true,
  121. });
  122. const pdf = await loadingTask.promise;
  123. var numPages = pdf.numPages;
  124. // that.loadedPages = that.numPages;
  125. if (numPages == 0) {
  126. return;
  127. }
  128. that.numPages = numPages;
  129. that.fileUrl = fileUrl;
  130. // await that.sleep(600);
  131. that.loadAll = true;
  132. that.loadedPages = numPages;
  133. // that.isLoading = false;
  134. // await that.sleep(2000);
  135. // that.isLoading = false;
  136. } catch (e) {
  137. console.error("PDF加载失败:", e);
  138. }
  139. },
  140. sleep(ms) {
  141. return new Promise((resolve) => setTimeout(resolve, ms));
  142. },
  143. ///截取文件
  144. getFileExtension(fileUrl) {
  145. var filename = fileUrl.split("/").pop();
  146. var lastDotIndex = filename.lastIndexOf(".");
  147. if (lastDotIndex === -1 || lastDotIndex === filename.length - 1) {
  148. return "";
  149. } else {
  150. return filename.substring(lastDotIndex + 1).toLowerCase();
  151. }
  152. },
  153. prevPage() {
  154. if (this.currentPage > 1) {
  155. this.currentPage--;
  156. }
  157. },
  158. nextPage() {
  159. if (this.currentPage < this.numPages) {
  160. this.currentPage++;
  161. }
  162. },
  163. scaleIn() {
  164. this.scale *= 1.1;
  165. },
  166. scaleOut() {
  167. this.scale /= 1.1;
  168. },
  169. async download() {
  170. var that = this;
  171. var name = that.name;
  172. var fileUrl = that.fileUrl;
  173. var fileName = that.getFileExtension(fileUrl);
  174. var finalName = "";
  175. if (name != null && name != "") {
  176. finalName = name + "." + fileName;
  177. } else {
  178. finalName = new Date().getTime() + "." + fileName;
  179. }
  180. try {
  181. // https://music-play.oss-cn-shenzhen.aliyuncs.com/backOss/file/f5f5ed93fae74fb683e8d116c40a884c.xlsx
  182. const response = await fetch(fileUrl);
  183. if (!response.ok) {
  184. throw new Error(`HTTP error! status: ${response.status}`);
  185. }
  186. const blob = await response.blob();
  187. const url = window.URL.createObjectURL(blob);
  188. const a = document.createElement("a");
  189. a.style.display = "none";
  190. a.href = url;
  191. a.download = finalName;
  192. document.body.appendChild(a);
  193. a.click();
  194. window.URL.revokeObjectURL(url);
  195. } catch (error) {}
  196. },
  197. },
  198. };
  199. </script>
  200. <style scoped>
  201. .container_all {
  202. width: 100vw;
  203. height: 100vh;
  204. }
  205. .container_public {
  206. width: 100vw;
  207. height: 100vh;
  208. overflow-y: auto;
  209. }
  210. .container_pdf {
  211. width: calc(100vw-2px);
  212. margin: 10px auto;
  213. border: 1px solid #e5e5e5;
  214. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  215. }
  216. .absolute_image1 {
  217. position: fixed;
  218. bottom: 365px;
  219. right: 20px;
  220. width: 30px;
  221. height: 30px;
  222. padding: 5px 5px;
  223. background-color: white;
  224. color: white;
  225. border: none;
  226. border-radius: 5px;
  227. cursor: pointer;
  228. }
  229. .absolute_image2 {
  230. position: fixed;
  231. bottom: 305px;
  232. right: 20px;
  233. width: 30px;
  234. height: 30px;
  235. padding: 5px 5px;
  236. background-color: white;
  237. color: white;
  238. border: none;
  239. border-radius: 5px;
  240. cursor: pointer;
  241. }
  242. .absolute_image3 {
  243. position: fixed;
  244. bottom: 260px;
  245. right: 20px;
  246. width: 30px;
  247. height: 30px;
  248. padding: 5px 5px;
  249. background-color: white;
  250. color: white;
  251. border: none;
  252. border-radius: 5px;
  253. cursor: pointer;
  254. }
  255. .fullscreen-loader {
  256. position: fixed;
  257. top: 0;
  258. left: 0;
  259. width: 100vw;
  260. height: 100vh;
  261. background: rgba(255, 255, 255, 1);
  262. display: flex;
  263. align-items: center;
  264. justify-content: center;
  265. }
  266. .loader {
  267. text-align: center;
  268. }
  269. .spinner {
  270. width: 50px;
  271. height: 50px;
  272. margin: 0 auto 15px;
  273. border: 3px solid #f3f3f3;
  274. border-top: 3px solid #409eff;
  275. border-radius: 50%;
  276. animation: spin 1s linear infinite;
  277. }
  278. @keyframes spin {
  279. 0% {
  280. transform: rotate(0deg);
  281. }
  282. 100% {
  283. transform: rotate(360deg);
  284. }
  285. }
  286. .tip {
  287. color: #606266;
  288. font-size: 14px;
  289. }
  290. </style>