details.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <template>
  2. <div class="details-p">
  3. <div class="tops">
  4. <div class="word">
  5. <van-icon class="word01" :name="'diy-' + fileType(detailData.docFileType)" />
  6. </div>
  7. <div class="title">{{detailData.docName}}</div>
  8. </div>
  9. <div class="middles">
  10. <h3>摘要</h3>
  11. <p>{{detailData.docSummary}}</p>
  12. <div class="continue" v-show="buyed == 0">全文共{{detailData.docPageSize}}页,<span @click="continued">继续阅读<van-icon name="arrow-down" size="18" /></span></div>
  13. </div>
  14. <div class="head-tip" id="fixedTop" :class="{'is-fixed':fixed}" v-show="buyed == 1">
  15. <h3 v-show="fixed">
  16. <van-icon class="word01" :name="'diy-' + fileType(detailData.docFileType)" />
  17. <span>{{detailData.docName}}</span>
  18. </h3>
  19. <span class="pages"><i id="page_num"></i> / <i id="page_count"></i></span>
  20. </div>
  21. <div class="botts" v-show="buyed == 1">
  22. <div class="cont-page" id="pdfPage"></div>
  23. </div>
  24. <van-goods-action>
  25. <van-goods-action-icon class="no-icon">
  26. <template #default>
  27. <p class="p1">剑鱼币</p>
  28. <p class="p2">{{detailData.price}}</p>
  29. </template>
  30. </van-goods-action-icon>
  31. <van-goods-action-icon icon="diy-jubao" text="投诉举报" @click="jubaod" />
  32. <van-goods-action-icon :icon="collectd==1?'diy-guanzhu':'diy-weiguanzhu'" :text="collectd==1?'已收藏':'收藏'" @click="canged" />
  33. <van-goods-action-button text="下载文档" @click="uploaded" />
  34. </van-goods-action>
  35. <!-- 充值 -->
  36. <recharge ref="charge" :detailData="detailData" :coins="coins"></recharge>
  37. <!-- 分享 -->
  38. <share-pop ref="shares" :detailData="detailData" :links="links"></share-pop>
  39. </div>
  40. </template>
  41. <script lang="ts">
  42. import { Component, Vue } from 'vue-property-decorator'
  43. import { mapActions } from 'vuex'
  44. import { Icon, Toast, GoodsAction, GoodsActionIcon, GoodsActionButton } from 'vant'
  45. import Recharge from '@/components/Recharge.vue'
  46. import sharePop from '@/components/SharePopup.vue'
  47. import { MixinTop } from '@/utils/mixin-top'
  48. import { weChatShare } from '@/utils/wxShare'
  49. const pdfjsLib = require('pdfjs-dist/build/pdf.js')
  50. const pdfjsViewer = require('pdfjs-dist/web/pdf_viewer.js')
  51. @Component({
  52. name: 'details-p',
  53. mixins: [MixinTop],
  54. components: {
  55. [Icon.name]: Icon,
  56. [GoodsAction.name]: GoodsAction,
  57. [GoodsActionIcon.name]: GoodsActionIcon,
  58. [GoodsActionButton.name]: GoodsActionButton,
  59. Recharge,
  60. sharePop
  61. },
  62. methods: {
  63. ...mapActions({
  64. getDetails: 'main/getDetails',
  65. getShow: 'main/getShow',
  66. getCoin: 'main/getCoin',
  67. getDown: 'main/getDown',
  68. getShare: 'main/getShare',
  69. getAdd: 'main/getAdd',
  70. getRemove: 'main/getRemove'
  71. })
  72. }
  73. })
  74. export default class extends Vue {
  75. getDetails: any
  76. getCoin: any
  77. getDown: any
  78. getShow: any
  79. getShare: any
  80. links: any = []
  81. docIds = ''
  82. fixed = false
  83. coins: any = []
  84. conts: any = []
  85. offsets: any = 0
  86. getAdd: any
  87. getRemove: any
  88. detailData: any = []
  89. collectd = 0
  90. buyed = 0
  91. pdfh5 = null
  92. pdfDocument: any
  93. config: any = {
  94. PAGE_TO_VIEW: 0,
  95. SCALE: 0,
  96. CMAP_URL: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/cmaps/',
  97. CMAP_PACKED: true,
  98. workerSrc: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/es5/build/pdf.worker.min.js'
  99. }
  100. pData: any = {
  101. heightList: []
  102. }
  103. TopConfig: any = {
  104. actionRightText: '<div style="display:flex;flex-direction: column;align-items: center;"><i class="j-icon icon-iconJianYu"></i><p style="color: #171826;font-size: 10px;line-height: 12px;margin-top:3px;">分享赚剑鱼币</p></div>',
  105. actionRightCallback: this.shared,
  106. actionRightStyle: {
  107. color: '#5F5E64',
  108. fontSize: '20px',
  109. paddingLeft: '10px'
  110. }
  111. }
  112. created () {
  113. this.docIds = this.$route.params.id
  114. this.onList()
  115. this.setTop()
  116. console.log(window.screen.width)
  117. }
  118. mounted () {
  119. // 监听滚轮
  120. window.addEventListener('scroll', this.initHeight)
  121. }
  122. destroyed () { // 移除监听
  123. window.removeEventListener('scroll', this.initHeight)
  124. }
  125. setTop () {
  126. this.$nextTick(() => {
  127. // 获取到达页面顶端的值
  128. const heights = document.getElementById('fixedTop')
  129. this.offsets = heights?.offsetTop
  130. // this.offsets = heights.getBoundingClientRect().top
  131. console.log(this.offsets)
  132. })
  133. }
  134. initHeight () {
  135. // 获取页面滚动距离
  136. const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
  137. this.fixed = !!(scrollTop > this.offsets && this.buyed)
  138. const top = window.scrollY
  139. let base = 0
  140. for (let i = 0; i < this.pData.heightList.length; i++) {
  141. base += this.pData.heightList[i]
  142. if (top <= base) {
  143. this.updateText({ type: 'num', value: i + 1 })
  144. break
  145. }
  146. }
  147. }
  148. async getShareUrl () {
  149. const { data } = await this.getShare({ docId: this.docIds })
  150. this.links = data.url || location.href
  151. // 注册微信sdk
  152. weChatShare({
  153. config: {
  154. title: this.detailData.docName,
  155. desc: this.detailData.docSummary,
  156. link: this.links
  157. }
  158. })
  159. }
  160. shared () {
  161. ;(this.$refs.shares as any).show = true
  162. }
  163. updateText (data: any) {
  164. console.log(data)
  165. switch (data.type) {
  166. case 'count': {
  167. ;(document.getElementById('page_count') as HTMLDivElement).textContent = data.value
  168. break
  169. }
  170. case 'num': {
  171. ;(document.getElementById('page_count') as HTMLDivElement).textContent = data.value
  172. break
  173. }
  174. }
  175. }
  176. renders () {
  177. const container = document.getElementById('pdfPage')
  178. // let notes = document.getElementById('pdfPage')
  179. // document.getElementById('pdfPage').style.width = '100vw'
  180. return this.pdfDocument.getPage(this.config.PAGE_TO_VIEW).then((pdfPage: any) => {
  181. const pdfPageView = new pdfjsViewer.PDFPageView({
  182. container: container,
  183. id: this.config.PAGE_TO_VIEW,
  184. scale: this.config.SCALE,
  185. defaultViewport: pdfPage.getViewport({ scale: this.config.SCALE }),
  186. eventBus: new pdfjsViewer.EventBus(),
  187. annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory()
  188. })
  189. pdfPageView.setPdfPage(pdfPage)
  190. this.pData.heightList.push(pdfPageView.viewport.height)
  191. return pdfPageView.draw()
  192. })
  193. }
  194. init () {
  195. console.log(this.conts)
  196. pdfjsLib.GlobalWorkerOptions.workerSrc = this.config.workerSrc
  197. const loadingTask = pdfjsLib.getDocument({
  198. url: this.conts,
  199. cMapUrl: this.config.CMAP_URL,
  200. cMapPacked: this.config.CMAP_PACKED
  201. })
  202. loadingTask.promise.then((pdfDocument: any) => {
  203. this.pdfDocument = pdfDocument
  204. console.log(this.pdfDocument.numPages)
  205. this.updateText({ type: 'count', value: this.pdfDocument.numPages })
  206. this.updateText({ type: 'num', value: 1 })
  207. for (let i = 0; i < this.pdfDocument.numPages; i++) {
  208. this.config.PAGE_TO_VIEW++
  209. this.renders()
  210. }
  211. })
  212. }
  213. watchPage () {
  214. const top = window.scrollY
  215. let base = 0
  216. for (let i = 0; i < this.pData.heightList.length; i++) {
  217. base += this.pData.heightList[i]
  218. if (top <= base) {
  219. this.updateText({ type: 'num', value: i + 1 })
  220. break
  221. }
  222. }
  223. }
  224. buyShow () {
  225. this.getShow({ docId: this.docIds }).then((res: any) => {
  226. console.log(res.data)
  227. this.conts = res.data
  228. this.init()
  229. })
  230. }
  231. onList () {
  232. this.getDetails({ docId: this.docIds, from: this.$route.query.from }).then((res: any) => {
  233. console.log(res.data)
  234. this.detailData = res.data.detail
  235. this.detailData.docSummary = res.data.detail.docSummary.split('').length >= 500 ? res.data.detail.docSummary + '...' : res.data.detail.docSummary
  236. this.buyed = res.data.status
  237. if (res.data.status === 1) {
  238. this.buyShow()
  239. }
  240. this.collectd = res.data.collect
  241. this.getShareUrl()
  242. })
  243. this.getCoin({ B: true }).then((res: any) => {
  244. console.log(res.data.data)
  245. this.coins = res.data.points
  246. })
  247. }
  248. jubaod () {
  249. Toast({
  250. duration: 3500,
  251. message: '如果您发现此内容有侵权行为,请联系客服400-108-6670进行投诉'
  252. })
  253. }
  254. canged () {
  255. if (this.collectd === 0) {
  256. this.getAdd({ docId: this.docIds }).then((res: any) => {
  257. console.log(res)
  258. if (res.error_code === 0) {
  259. this.collectd = 1
  260. Toast('收藏成功')
  261. }
  262. })
  263. } else {
  264. this.getRemove({ docId: this.docIds }).then((res: any) => {
  265. console.log(res)
  266. if (res.error_code === 0) {
  267. this.collectd = 0
  268. Toast('取消收藏')
  269. }
  270. })
  271. }
  272. }
  273. continued () {
  274. this.uploaded()
  275. }
  276. uploaded () {
  277. if (this.buyed === 1) {
  278. this.getDown({ docId: this.docIds }).then((res: any) => {
  279. if (res.error_code === 0) {
  280. window.location.href = res.data
  281. }
  282. })
  283. } else {
  284. if (this.coins.balance < this.detailData.price) {
  285. ;(this.$refs.charge as any).show = true
  286. } else {
  287. this.$router.replace('/purchase/' + this.detailData.docId)
  288. }
  289. }
  290. }
  291. fileType (val: any) {
  292. if (val === 1) {
  293. return 'word'
  294. } else if (val === 2) {
  295. return 'pdf'
  296. } else if (val === 3) {
  297. return 'excel'
  298. } else if (val === 4) {
  299. return 'ppt'
  300. } else if (val === 5) {
  301. return 'txt'
  302. } else {
  303. return ''
  304. }
  305. }
  306. }
  307. </script>
  308. <style lang="scss" scoped>
  309. @include diy-icon('pdf', 24, 24);
  310. @include diy-icon('word', 24, 24);
  311. @include diy-icon('excel', 24, 24);
  312. @include diy-icon('ppt', 24, 24);
  313. @include diy-icon('jubao', 20, 20);
  314. @include diy-icon('weiguanzhu', 20, 20);
  315. @include diy-icon('guanzhu', 20, 20);
  316. @include diy-icon('iconJianYu', 24, 24);
  317. .details-p {
  318. display: flex;
  319. flex-direction: column;
  320. padding-bottom: 80px;
  321. .tops {
  322. display: flex;
  323. flex-direction: initial;
  324. background: #fff;
  325. padding: 24px 16px;
  326. .word {
  327. display: flex;
  328. }
  329. .word01 {
  330. display: flex;
  331. width: 24px;
  332. height: 24px;
  333. margin-right: 8px;
  334. }
  335. .title {
  336. color: #171826;
  337. font-weight: 500;
  338. font-size: 20px;
  339. line-height: 30px;
  340. }
  341. }
  342. .middles {
  343. padding: 16px;
  344. background: #fff;
  345. margin: 8px 0;
  346. h3 {
  347. font-size: 16px;
  348. line-height: 24px;
  349. font-weight: 500;
  350. color: #171826;
  351. }
  352. p {
  353. color: #5F5E64;
  354. font-size: 14px;
  355. line-height: 20px;
  356. margin-top: 8px;
  357. }
  358. .continue {
  359. color: #5F5E64;
  360. font-size: 14px;
  361. line-height: 20px;
  362. text-align: center;
  363. margin-top: 32px;
  364. span {
  365. display: inline-flex;
  366. align-items: center;
  367. color: #2ABED1;
  368. cursor: pointer;
  369. i {
  370. margin-left: 4px;
  371. }
  372. }
  373. }
  374. }
  375. .head-tip {
  376. width: auto;
  377. height: 60px;
  378. background: #fcfcfc;
  379. display: flex;
  380. justify-content: flex-end;
  381. align-items: center;
  382. padding: 0 16px;
  383. border-bottom: 1px solid #F2F2F4;
  384. h3 {
  385. display: flex;
  386. align-items: center;
  387. span {
  388. width: 260px;
  389. color: #686868;
  390. font-weight: 500;
  391. font-size: 14px;
  392. line-height: 24px;
  393. overflow: hidden;
  394. text-overflow:ellipsis;
  395. white-space: nowrap;
  396. }
  397. i {
  398. margin-right: 8px;
  399. }
  400. }
  401. .pages {
  402. color: #686868;
  403. font-size: 14px;
  404. i:first-child {
  405. display: inline-block;
  406. font-style: normal;
  407. width: 16px;
  408. height: 16px;
  409. line-height: 18px;
  410. text-align: center;
  411. border-radius: 2px;
  412. background: #FFFFFF;
  413. border: 1px solid #ECECEC;
  414. }
  415. }
  416. }
  417. .is-fixed {
  418. position: fixed;
  419. top: 0;
  420. justify-content: space-between;
  421. }
  422. .botts {
  423. // padding: 16px 24px;
  424. // width: 375px;
  425. background: #fff;
  426. .cont-page {
  427. // width: 375px;
  428. overflow-y: scroll;
  429. background: #fff;
  430. }
  431. }
  432. .van-goods-action {
  433. // height: 56px;
  434. padding: 8px 16px;
  435. box-shadow: 0px -2px 8px 0px #eee;
  436. display: flex;
  437. justify-content: space-between;
  438. .no-icon {
  439. .p1 {
  440. font-size: 12px;
  441. line-height: 18px;
  442. color: #5F5E64;
  443. }
  444. .p2 {
  445. font-size: 18px;
  446. line-height: 26px;
  447. color: #FB483D;
  448. }
  449. .van-icon {
  450. display: none!important;
  451. }
  452. }
  453. .van-goods-action-icon:not(.no-icon) {
  454. font-size: 10px;
  455. color: #5F5E64;
  456. }
  457. .van-goods-action-button--first {
  458. margin-left: 0;
  459. }
  460. .van-goods-action-button--last {
  461. margin-right: 0;
  462. }
  463. .van-goods-action-button {
  464. flex: none;
  465. }
  466. .van-button--large {
  467. width: 165px;
  468. height: 40px;
  469. }
  470. ::v-deep .van-button--default {
  471. background-color: #2ABED1;
  472. .van-button__content {
  473. .van-button__text {
  474. color: #fff;
  475. font-size: 16px;
  476. }
  477. }
  478. }
  479. }
  480. }
  481. </style>